2017-10-28 78 views
3

考慮以下,最小的例子,當不編譯(編譯沒有#1#2):C++模板通過函數簽名

void foo(void) 
{ } 

template<typename T> class Stage2; 

template<typename Ret, typename... Args> 
struct Stage2<Ret (Args...)> 
{ 
    template<Ret (*func)(Args...)> 
    static void foobar(void) 
    { /* Do something */ } 
}; 

template<typename FuncType> 
struct Stage1 
{ 
    template<FuncType func> 
    static void bar(void) 
    { 
     Stage2<FuncType>::foobar<func>();  // #1, Not working 
     Stage2<decltype(func)>::foobar<func>(); // #2, Not working 
     Stage2<void()>::foobar<func>();   // #3, Working 
    } 
}; 

int main(void) 
{ 
    Stage1<decltype(foo)>::bar<foo>(); 
    return 0; 
} 

爲何不與#1#2編譯,而它編譯只是#3罰款?在我看來,只要foo的簽名爲void()#3應該與其他人相同,在本例中它就是這樣做的。即使編譯器告訴我,FuncType實際上是void()(見下文)。

錯誤信息(同爲#1#2):

main.cpp: In static member function ‘static void Stage1<FuncType>::bar()’: 
main.cpp:21:40: error: expected primary-expression before ‘)’ token 
     Stage2<FuncType>::foobar<func>();  // #1, Not working 
             ^
main.cpp: In instantiation of ‘static void Stage1<FuncType>::bar() [with FuncType func = foo; FuncType = void()]’: 
main.cpp:29:37: required from here 
main.cpp:21:33: error: invalid operands of types ‘<unresolved overloaded function type>’ and ‘void (*)()’ to binary ‘operator<’ 
     Stage2<FuncType>::foobar<func>();  // #1, Not working 
     ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~ 

缺少什麼我在這裏?我正在使用g ++ 7.2.0。

注意:如果這樣做有用,我不會真正感興趣,我只想知道它爲什麼不編譯,因爲它對我沒有意義。

回答

2

基本上,這是怎麼回事是這樣的:

Stage2<FuncType>::foobar<func>(); 

包含(取決於FuncType)一個從屬名稱,因此你必須按照正確的C++ - 語法調用成員模板(因此,語法錯誤消息) ,這是

Stage2<FuncType>::template foobar<func>(); 

注意,這並不適用於作爲Stage2<void()>::foobar<func>();有沒有涉及相關的名稱。

這同樣適用於Stage2<decltype(func)>::foobar<func>();,但僅靠這一點仍不能解決問題,因爲存在一些棘手的障礙。根據§14.1.8[temp.param],

類型爲「T的數組」或「返回T的函數」類型的非類型模板參數被調整爲類型爲「指向T的指針」或「指向函數返回T的指針」。

decltype(func)void(*)()代替void()(即使FuncType被指定爲void()),所以沒有功能類型,但函數指針類型將作爲模板參數Stage2對於其中不存在提供專業化傳遞(如Stage2<Ret (Args...)>Stage2<Ret (*)(Args...)>不一樣),因此回落到默認模板聲明,最終產生「使用不完整類型」錯誤。

+0

從來沒有聽說過這種語法,很高興知道。謝謝! – Shadowigor