我有两个版本的 my_begin
:
template<typename T, typename std::enable_if<std::is_array<T>::value>::type* = 0>
typename std::decay<T>::type my_begin(T& array) {
return array;
}
和
template<typename T>
typename std::decay<T>::type my_begin(T& array,
typename std::enable_if<std::is_array<T>::value>::type* = 0) {
return array;
}
但是第一个不起作用并给出错误:
int a[10];
int* a_it = my_begin(a);
错误:
main.cpp:17:30: note: template argument deduction/substitution failed:
main.cpp:16:80: error: could not convert template argument '0' to 'std::enable_if<true, void>::type* {aka void*}'
template<typename T, typename std::enable_if<std::is_array<T>::value>::type* = 0>
但是第二个有效。当我将第一个中的 0 更改为 nullptr 时,它也有效(但仍然不适用于 NULL)。我知道在模板中它需要显式转换(在这种情况下,从 int
到 void*
,但为什么第二个不需要它?
另外一个问题,如果我去掉*
和=
之间的空格,也是失败的。这是为什么?
最佳答案
§14.1 [temp.param]/p4 说:
A non-type template-parameter shall have one of the following (optionally cv-qualified) types:
- integral or enumeration type,
- pointer to object or pointer to function,
- lvalue reference to object or lvalue reference to function,
- pointer to member,
std::nullptr_t
.
从字面上看,这不允许 void*
完全模板参数。 void*
是一个对象指针类型但不是指向对象类型的指针(§3.9.2 [basic.compound]/p3):
The type of a pointer to
void
or a pointer to an object type is called an object pointer type. [ Note: A pointer tovoid
does not have a pointer-to-object type, however, becausevoid
is not an object type. —end note ]
如果我们假设它是一个缺陷并且标准真的意味着“对象指针类型”,那么使用 0
并且 company 仍被 §14.3.2 [temp.arg.nontype]/p5(添加了强调)所禁止:
The following conversions are performed on each expression used as a non-type template-argument. If a non-type template-argument cannot be converted to the type of the corresponding template-parameter then the program is ill-formed.
- [...]
- for a non-type template-parameter of type pointer to object, qualification conversions (4.4) and the array-to-pointer conversion (4.2) are applied; if the template-argument is of type
std::nullptr_t
, the null pointer conversion (4.10) is applied. [ Note: In particular, neither the null pointer conversion for a zero-valued integer literal (4.10) nor the derived-to-base conversion (4.10) are applied. Although 0 is a valid template-argument for a non-type template-parameter of integral type, it is not a valid template-argument for a non-type template-parameter of pointer type. However, both(int*)0
andnullptr
are valid template-arguments for a non-type template-parameter of type “pointer to int.” —end note ]
= 0
适用于函数默认参数,因为它们遵循正常的转换规则,允许值为 0 的整数文字转换为空指针,而不是模板参数的特殊规则。
if I remove the whitespace between * and =, it also failed. Why is that?
最大咀嚼。如果删除空格,*=
是单个标记(复合赋值运算符)。就像在 C++03 中你必须在 >
之间放置一个空格一样在std::vector<std::vector<int> >
.
关于c++ - 为什么 void* 作为模板参数作为函数参数而不是模板参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26290770/