如何用文字0和指针解决对重载函数的调用歧义

时间:2011-01-05 23:59:17

标签: c++ templates overloading overload-resolution

我很确定这一定已经在这里了,但是我没有找到很多关于如何解决这类问题的信息(没有在电话上播出):

给定两个重载,我希望一个带有文字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 个答案:

答案 0 :(得分:3)

你在做什么2)工作,可能是更好的方法。

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

func((void *) 0);
func((unsigned int) 0);

答案 1 :(得分:3)

我建议你看一下C ++ 0x的空指针(参见this)。它定义了一个表示任何类型的空指针的类。您刚刚给出的示例实际上是一个激励将nullptr_t(类)/ nullptr(值)包含在C ++ 0x中。它实际上允许您通过在想要 unsigned int 版本时输入0来消除歧义,并在需要另一个时使用 nullptr

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

答案 2 :(得分:2)

  

1)是否有建议的方法来执行此操作?

是的,我会像你在2)那样做。我不认为为什么2)工作有更深层的含义。类型intT*不匹配,因此无法找到T。因此会忽略模板。

答案 3 :(得分:2)

  

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

问题很简单,文字0int,而不是unsigned int,并且有intunsigned int和来自int的有效转化void*void func(int i) { assert(i >= 0); return func(static_cast<unsigned int>(i)); } 。我不能说有一种推荐的方法来处理这个问题。除了你已经找到的方法,你还可以添加另一个重载:

{{1}}
  

2)以下列方式进行操作是否有任何问题?这是什么原因可以解决?

模板技巧之所以有效,是因为解析对重载函数和模板版本的函数的调用规则是为了更喜欢重载函数的非模板化版本。