2014-12-05 166 views
1

我試圖編譯以下行的代碼和它失敗:模板參數推導C++

template <typename T> 
struct InputBlockParameterType { 
    typedef T type; 
}; 

template <typename T, template <typename> class BlockTypeTrait> 
struct BlockParameterImpl { 
    typedef typename BlockTypeTrait<T>::type type; 
}; 

template <typename T> 
struct InputBlockParameter { 
    typedef typename BlockParameterImpl<T, InputBlockParameterType>::type type; 
}; 


struct Functor { 
    template <typename T> 
    bool operator()(typename InputBlockParameter<T>::type p) { 
     return true; 
    } 
}; 

int main() { 
    InputBlockParameter<double>::type arg = 0.0; 

    Functor f; 
    f(arg); 

    return 0; 
} 

該錯誤是(MSVC 2013):

1>main.cpp(31): error C2783: 'bool Functor::operator()(InputBlockParameter<T>::type)' : could not deduce template argument for 'T' 
1>   main.cpp(21) : see declaration of 'Functor::operator()' 

如果我改變算符到

struct Functor { 
    template <typename T> 
    bool operator()(T p) { 
     return true; 
    } 
}; 

所有事情都按預期編譯。

爲什麼代碼的第一個版本不能編譯?它是否在標準中定義的某個地方?

+2

'::'左側的所有內容都是未推演的上下文。 – 2014-12-05 13:01:50

回答

4

扣除僅適用於推導的上下文。

哪個是無用的:X只在X有效時起作用。我可以引用標準,但它只是說「是的,這是行不通的」,難以閱讀散文。

想想它的最好方法是編譯器只是模式匹配。但是,它不會搜索或嘗試反轉您編寫的任何類型的映射。

foo<T>::type可以做一個圖靈完備的計算(最高編譯器限制)從Ttype:這樣的標準宣佈採用T那裏是非推斷背景下,即使foo類型映射似乎很容易反過來給你。即使我們已經要求它們是Turing complete來編譯C++,但是要求編譯器去做任意函數並不是一個實際的事情。

編譯器將不會轉換(除了base和cv剝離和參數衰減),或者在模板類型扣除期間反轉類型映射。它只是模式匹配的論據。

它將按照SFINAE目的的類型映射,但理論上這更容易。

如果您可以自己編寫逆映射,則可以使用SFINAE和默認參數以及模板類專業化和轉發的混合來獲得您可能需要的效果。