为什么不允许使用0作为void*的默认非类型模板参数
Why using 0 as default non type template parameter for void* is not allowed
为什么下面的代码无法编译?尽管void* ptr = 0;
template <void* ptr = 0>
void func();
int main() {
func();
return 0;
}
我问这个问题是因为我发现一个非常可信的源代码做了类似的事情,并且在我的机器上无法编译
注意应该在我的问题中发布编译器错误,所以这里是
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();
^
不允许使用void*
类型的模板参数。参见标准中的[temp.param]/4,也总结在http://en.cppreference.com/w/cpp/language/template_parameters#Non-type_template_parameter
非类型模板参数应具有以下类型之一(可选cv-qualified):
- 整型或枚举型,
- 指向对象或指向函数的指针,
- 左值指向对象或左值指向函数
- 指针指向成员,
std::nullptr_t
.
由于void
不是对象或函数类型,因此void*
不在允许的类型之列。
附录:编译时已知的void*
值不是很有用。不可能在编译时检查它的值,因为reinterpret_cast
不允许在常量表达式中使用;也不可能在编译时将某些对象类型T
转换为T*
。
您尝试使用int
初始化指针。许多隐式转换,包括整型到指针的转换,都不会在非类型模板形参中发生。
c++ 14中指向对象类型的指针的非模板形参的行为的cppreference总结为:
对于指向对象的指针,模板实参必须指定具有静态存储时间和链接(内部或外部)的对象的地址,或者指定计算结果为适当的空指针或std::nullptr_t值的常量表达式。
所以代码可以是:
template <void* ptr = nullptr>
void f();
脚注:似乎不清楚void *
是否被允许作为参数类型,但编译器接受上述代码。
相关文章:
- 具有默认模板类型的默认构造函数的类型推导
- C++(和 ROS) - 包含与前向声明引用,设置默认值和类型定义
- 模板类默认类型和条件
- 具有默认类型和值的模板参数
- 在一行中将默认类型值上的指针作为参数传递
- 模板中默认类型的重载运算符
- 当“std::make_index_sequence”和“std::index_sequence”用于模板参数默认类型时
- 所有版本的 GCC 都在与定义中具有默认类型的模板作斗争
- 有关为模板提供默认类型的问题
- eigen:模板函数中矩阵的默认类型
- 可以将枚举的默认类型设置为无符号字符
- 是否可以为缺少的模板成员类型创建默认类型?
- 如何在C++中为类返回默认类型
- 函数模板:默认类型参数
- 模板默认类型vs默认值
- 使用默认类型替换c++函数引用模板错误
- 模板函数的默认类型假设
- 在C++中,用十六进制或八进制表示的整型文字的默认类型是什么
- 如何在c++中定义默认类型转换操作符
- 错误:不明确的默认类型转换(c++)