12

我很确定这一定已经在这里了,但是我没有找到很多关于如何解决这类问题的信息(没有在通话中进行投射):

给定两个重载,我希望带有文字 0 的函数调用始终调用 unsigned int 版本:

void func( unsigned int ) {
    cout << "unsigned int" << endl;
}

void func( void * ) {
    cout << "void *" << endl;
}

func( 0 ); // error: ambiguous call

我理解为什么会发生这种情况,但我不想一直写 func( 0u ) 甚至 func( static_cast(0) ) 。所以我的问题是:

1)一般有推荐的方法吗?

2)按照以下方式进行操作有什么问题吗?这样做的原因是什么?

void func( unsigned int ) {
    cout << "unsigned int" << endl;
}

template <typename T>
void func( T * ) {
    static_assert( std::is_same<T, void>::value, "only void pointers allowed" );
    cout << "void *" << endl;
}

func( 0 ); // calls func( unsigned int )!
4

4 回答 4

3

我建议您查看 C++0x 中的空指针(请参阅this)。它定义了一个表示任何类型的空指针的类。您刚刚给出的示例实际上是促使将 nullptr_t(类)/nullptr(值)包含到 C++0x 中的一个示例。它实际上可以让您通过在需要unsigned int版本时输入 0 来消除此调用的歧义,而当您想要另一个时输入nullptr 。

你可以在一个小的实用程序类中实现这个技巧,直到你的编译器支持它(或者如果你的编译器实现了下一个标准的这一部分,就使用它)。

于 2011-01-06T00:08:16.000 回答
3

您在 2) 中所做的工作有效,并且可能是更好的方法。

在您不想更改函数的情况下,您可以进行显式转换以向编译器提示:

func((void *) 0);
func((unsigned int) 0);
于 2011-01-06T00:03:27.140 回答
2

1)一般有推荐的方法吗?

问题很简单,文字0是一个int,而不是一个,并且从to和 from tounsigned int有有效的转换。我不能说有一个推荐的方法来处理这个问题。除了您已经找到的方式之外,您还可以添加另一个重载:intunsigned intintvoid*

void func(int i) 
{
    assert(i >= 0);
    return func(static_cast<unsigned int>(i));
}

2)按照以下方式进行操作有什么问题吗?这样做的原因是什么?

模板技巧之所以有效,是因为解析对重载并具有模板版本的函数的调用的规则旨在首选重载函数的非模板版本。

于 2011-01-06T00:13:29.453 回答
2

1)一般有推荐的方法吗?

是的,我会按照您在 2) 中的方式进行操作。我认为为什么 2) 有效没有任何更深层次的含义。类型int根本不匹配T*,所以没有办法找出来T。因此它将忽略模板。

于 2011-01-06T00:01:51.523 回答