2014-10-10 131 views
3

我有两个版本的my_begin为什么void *作为模板参数而不是模板参数?

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)。我不明白,在模板它需要显式类型转换(在这种情况下,从intvoid*,但为什么第二个不需要吗?

另一个问题是,如果我删除*=之间的空白,它也失败了?这是为什么

回答

9

§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 to void does not have a pointer-to-object type, however, because void is not an object type. —end note ]

(强调)指针”,然后使用0和公司仍然由§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 and nullptr are valid template-arguments for a non-type template-parameter of type “pointer to int.” —end note ]

= 0作品函数默认参数,因为这些都受到了正常的转换规则,它允许一个值为0的整数字面值转换为空指针,而不是特殊规则f或模板参数。


if I remove the whitespace between * and =, it also failed. Why is that?

最大蒙克。如果删除了空格,则*=是单个标记(复合赋值运算符)。就像在C++ 03中一样,你必须在std::vector<std::vector<int> >>之间加一个空格。

+0

感谢您的详细解答! – texasbruce 2014-10-10 04:13:35