2017-10-28 55 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