2010-07-24 93 views
2

使用SFINAE對於一些複雜的原因,追趕函子,我想任何支持T型(從模板來)轉換成的我選擇類型的列表。爲此,我嘗試使用名爲「Convert」的模板結構。例如:結構偏特

Convert<short>::type should be int 
Convert<int>::type should be int 
Convert<char>::type should be int 
Convert<float>::type should be double 
Convert<double>::type should be double 
Convert<const char*>::type should be std::string 
Convert<std::string>::type should be std::string 
etc. 

上面的內容很容易使用模板專門化來實現。但有一種情況是導致問題:

Convert<T>::type where T is a functor should be T 

爲了解決這個問題,我想我必須使用SFINAE但我不能設法讓它編譯。

下面的代碼給了我「partial specialization cannot match argument list for primary template」(即寫「轉換」禁止):

template<typename T, typename = decltype(&T::operator())> 
struct Convert<T>  { typedef T type; }; 

而這一次給了我「template parameter not used or deducible in partial specialization」(即它認爲,不使用T):

template<typename T> 
struct Convert<typename std::enable_if<std::is_function<typename T::operator()>::value,T>::type> 
{ typedef T type; }; 

我不知道該怎麼做,我所有的嘗試都會導致上述兩個錯誤之一。

編輯:我想搭上使用同一模式的其他普通的事情,所以我不能只寫「的typedef T形」的非專業結構。

感謝

+0

你是什麼意思「抓其他通用的東西」? – GManNickG 2010-07-24 09:34:54

+0

你需要澄清你的意思是「一個仿函數」。功能還不錯?或者它只是功能對象?如果是這樣,那麼用operator()'超載的任何東西?或從'std :: function_object'派生?特定數量的參數? – sbi 2010-07-24 09:42:09

+0

實例:「轉換 ::類型是int如果T是可轉換爲int」,或「轉換 ::類型是...如果T具有開始和結束功能」等 – Tomaka17 2010-07-24 09:44:58

回答

2

我建議你使用第一種方法,但要使其工作,你就必須

有一個未使用的模板參數聲明主模板:

template <class T, class = void> Convert; 

void參數添加到您現在使用的模板的所有特化。

定義你的「仿函數專業化」是這樣的:

template<typename T, typename std::enable_if<std::is_function<typename T::operator()>::value,void>::type> 

這意味着你做的第二個參數void,如果它是一個仿函數(所以它的默認模板參數匹配)或不存在的,如果它不是。

BTW你爲什麼要使用typename T::operator()typename? AFAIK,operator()不是一種類型。

+0

好主意,謝謝。顯然,我甚至不需要在我的其他專業上添加「void」。然而,編譯器暫時使用非特殊化的結構,我會盡力使其工作。 – Tomaka17 2010-07-24 10:49:45

+0

你可能是正確的typename,無論如何我嘗試了幾個東西,如'std :: enable_if <!std :: is_void :: value> :: type',我認爲是正確 – Tomaka17 2010-07-24 10:51:39

+0

'Convert :: type>'正在工作,所以在我的情況下肯定有問題 – Tomaka17 2010-07-24 11:05:25