为什么不允许使用0作为void*的默认非类型模板参数

Cur*_*ous 8 c++ templates void c++11 c++14

为什么以下代码无法编译?即使这样做也是合法的void* ptr = 0;

template <void* ptr = 0>
void func();

int main() {
    func();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我问,因为我发现一个非常值得信赖的来源做了类似的事情,但无法在我的机器上编译

注意应该已经发布了编译器错误以及我的问题,所以在这里

so_test.cpp:1:23: error: null non-type template argument must be cast to template parameter type 'void *'
template <void* ptr = 0>
                      ^
                      static_cast<void *>( )
so_test.cpp:1:17: note: template parameter is declared here
template <void* ptr = 0>
                ^
so_test.cpp:5:5: error: no matching function for call to 'func'
    func();
    ^~~~
so_test.cpp:2:6: note: candidate template ignored: substitution failure [with ptr = nullptr]: null non-type template argument must be cast to template parameter type 'void *'
void func();
     ^
Run Code Online (Sandbox Code Playgroud)

Bri*_*ian 9

void*不允许使用类型的模板参数.请参阅标准中的[temp.param]/4,也可在http://en.cppreference.com/w/cpp/language/template_parameters#Non-type_template_parameter中进行总结.

非类型模板参数应具有以下之一(可选的cv限定)类型:

  • 积分或枚举类型,
  • 指向对象或指向函数的指针,
  • 左值引用对象或左值引用函数,
  • 指向成员的指针,
  • std::nullptr_t.

由于void不是对象或函数类型,void*因此不属于允许的类型.

附录:void*编译时已知的值不是很有用.由于reinterpret_cast在常量表达式中不允许,因此无法在编译时检查其值; 也不可能在编译时将其转换T*为某种对象类型T.

  • @ Petr'lapk'Budnik我担心C++标准不同意你的看法. (3认同)
  • @petr我担心接受代码的编译器只是代码合法的弱证据.标准中的引文要强得多.不可否认,布莱恩只有一个cppreference引用,也有弱证据. (3认同)