2010-05-23 48 views
2

我想創建一組重載模板的數組/指針,其中一個模板將用於編譯器知道數組的大小和另一個模板將用於它不' t:可以使這些模板明確

template <typename T, size_t SZ> 
void moo(T (&arr)[SZ]) 
{ ... } 

template <typename T> 
void moo(T *ptr) 
{ ... } 

問題是,當編譯器知道數組的大小時,重載模糊不清,編譯失敗。

有什麼方法可以解決歧義(也許通過SFINAE)或者這是不可能的。

+0

不應該第二個重載有'size_t'參數或東西,所以該功能就會知道'ptr'指向的數組大小? – 2010-05-23 01:19:41

+0

指針版本不一定非要用於動態數組。 @ins – 2010-05-23 05:11:33

+0

好問題,我偶然發現了完全相同的問題。對於記錄來說,模糊會出現,因爲在重載解析期間,數組到指針的轉換被認爲是完全匹配(第13.3.3.1.1節)。我不覺得這是一種非常直觀的行爲,而且我很想知道爲什麼會做出這樣的決定。 – 2011-08-10 14:46:33

回答

5

這是可能,因爲它可以閹模板參數來確定是一個數組或不:

template<class T> struct is_array { 
    enum { value = false }; 
}; 
template<class T, size_t N> struct is_array<T[N]> { 
    enum { value = true }; 
}; 
template<class T> void f(T const&) { 
    std::cout << is_array<T>::value << std::endl; 
} 

結合與enable_if,上述可製成無歧義。例如使用Boost.TypeTraits:

template <typename T, size_t SZ> 
typename boost::enable_if<boost::is_array<T>, void>::type 
f(T (&arr)[SZ]) {} 

隨着引用但沒有必要在SFINAE所有:

template<class T, size_t SZ> void f(T (&arr)[SZ]) {} 
template<class T>   void f(T* const& t) {} 

約翰內斯帶來了,在手更符合情況的另一種選擇 - 使用SFINAE爲有問題的指針,而不是過載:

template <typename T, size_t SZ> void f(T (&arr)[SZ]) {} 
template <typename T> 
typename boost::enable_if<boost::is_pointer<T>, void>::type 
f(T ptr) {} 
+1

如果將第二個函數更改爲'T * const&t',則甚至可以接受右值指針表達式。爲了說明他將如何在*他的場景中使用你的模板:'template void f(T(&arr)[SZ]){} typename disable_if < is_array> :: type void f(T const& t){}'。最終,我會使用'is_pointer'來執行'enable_if',因爲它是數組綁定到引發問題的'T *',而不是綁定到'T [N]'的指針(這不起作用)。 – 2010-05-23 17:53:13

+0

@Johannes:我想我傾向於忽略rvalues,直到他們打我。像往常一樣,感謝您的輸入:) – 2010-05-23 18:38:30

0

你可以調用函數明確:

int a[1] = {0} 
moo<int,1>(a); 

或者您也可以常量重載:

template<class T> 
void moo(T const* p) { } 

// ... 
moo(a); // not const, array 

int* p = 0; 
moo(p); // pointer 
2

而且可能是最簡單的解決方案:

template <typename T, size_t SZ> 
void moo(T (&arr)[SZ]) 
{ ... } 

template <typename T> 
inline void moo(T ptr) { __moo(ptr); } 

template <typename T> 
void __moo(T* ptr) 
{ ... }