2014-10-10 132 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