通过函数模板传递时无法从0构造指针

时间:2013-11-19 20:07:07

标签: c++

假设我有一个任意类型:struct Bar {};。我想从0构造一个Bar*,我可以明确地做到这一点:

Bar* b = 0; 

我甚至可以通过函数调用隐式地执行它:

void foo(Bar* b) { Bar* x = b; }

foo(0);

但是当我通过函数模板传递0时,该能力消失了:

template <typename T>
void foo(T t) {
    Bar* x = t;
}

foo(0); // error: invalid conversion from ‘int’ to ‘Bar*’

为什么不呢?另外两种不再适用的配方有什么特别之处?

2 个答案:

答案 0 :(得分:6)

初始化指向0的指针与0(即int字面值)到Bar*的类型推导不同。因此错误。

为了符合标准,请使用nullptr关键字而不是普通0字面值来解除类型。< 另请注意,使用旧的NULL宏的pre-c ++ 11标准实现可能比普通0文字更好,因为NULL通常会扩展为(void*)0使用模板和指向模板参数类型的指针时会有所不同。

对于(略微错误的)模板函数定义

template <typename T>
void foo(T* t) {
      // ^^ Note!
    T* x = t;
 // ^ Note!
}

以下代码应该用C ++ 11编译为

foo(nullptr); // C++11

和Pre C ++ 11

foo((void*)0); // NULL didn't work for IDEONE GCC 4.8 and including 
               // <cstddef>. I'd expect it to expand to (void*)0, but 
               // it seems expanding to (int*)0 ?!?

<强>更新
如果要确保传递的指针类型符合某些基类指针类型,则需要显式转换:

template <typename T>
void foo(T* t) {
    Bar* x = static_cast<Bar*>(t);
}

但是你必须将具体的指针类型传递给函数:

class Derived : public Bar
{
    // Blah!
};

Derived* x = 0;

foo(derived);

static_cast不适用于void指针!

答案 1 :(得分:3)

零很特别。可以将零作为常量分配给表示空指针的指针。但是你不能在没有强制转换的情况下将int赋值给一般的指针。