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

Cannot construct pointer from 0 when passed through a function template

本文关键字:指针 函数模板      更新时间:2023-10-16

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

Bar* b = 0; 

我甚至可以通过函数调用隐式地完成:

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

但当我通过函数模板:时,这种能力就消失了

template <typename T>
void foo(T t) {
    Bar* x = t;
}
foo(0); // error: invalid conversion from ‘int’ to ‘Bar*’

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

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

为了符合c++11标准,请使用nullptr关键字而不是普通的0文字来取消对类型的模糊化
还要注意的是,对于c++11之前的标准实现,使用好的旧NULL宏可能比普通的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指针!

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