2011-12-15 107 views
7

這是我的代碼來檢查類是否有成員函數begin與否:模板實例混亂

template<typename T> struct has_begin 
{ 
    struct dummy {typedef void const_iterator;}; 
    typedef typename std::conditional< has_iterator<T>::yes, T, dummy>::type TType; 
    typedef typename TType::const_iterator Iter; 
    struct fallBack{ Iter begin() const ; Iter end() const;}; 
    struct checker : T, fallBack {}; 
    template <typename B, B> struct cht; 
    template<typename C> static char check(cht< Iter (fallBack::*)() const, &C::begin>*); // problem is here 
    template<typename C> static char (&check(...))[2]; 
public: 
    enum {no = (sizeof(check<checker>(0))==sizeof(char)), 
    yes=!no}; 
}; 

如果我更改了check(cht< Iter (fallBack::*)() const, &C::begin>*);cht秒參數 &checker::begin,這並不改變語義的代碼因爲的cht秒模板參數始終checker由於這種enum {no = (sizeof(check<checker>(0))==sizeof(char))

但代碼變化導致error現在它們是:

prog.cpp: In instantiation of 'has_begin<std::vector<int> >': 
prog.cpp:31:51: instantiated from here 
prog.cpp:23:38: error: reference to 'has_begin<std::vector<int> >::checker::begin' is ambiguous 

我想知道這是什麼原因背後的原因。

+0

你的結構非常複雜。它應該做什麼?看起來像一個檢查,如果類T有一個名爲開始 – 2011-12-15 10:23:00

+0

@VJovic成員函數你是對的,我編輯了Q的第一行:) – 2011-12-15 10:28:45

回答

3

從維基百科的文章約SFINAE - 換人失敗是不是一個錯誤:

[...] when creating a candidate set for overload resolution, some (or all) candidates of that set may be the result of substituting deduced template arguments for the template parameters. If an error occurs during substitution, the compiler removes the potential overload from the candidate set instead of stopping with a compilation error [...]

在你的代碼貼出來,同時用參數C == typename has_begin<T>::checker實例函數模板check出現多義性錯誤,那替換會導致錯誤,因此實例化只是從過載集合中刪除。

如果更改代碼,則會發生與&checker::begin類似的多義性錯誤。 但是,這次不是將模板參數C替換爲check函數模板的結果。模板參數T的替代struct has_begin與SFINAE規則無關,因爲該模板已經成功實例化。