考虑以下最小的例子(没有#1和编译#2):
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;
}
Run Code Online (Sandbox Code Playgroud)
为什么它不能编译#1和#2,而它编译得很好#3?在我看来,#3只要foo具有签名void(),它应该等同于其他人,在本例中它就是这样.甚至编译器也告诉我,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
~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
Run Code Online (Sandbox Code Playgroud)
我在这里错过了什么?我正在使用g ++ 7.2.0.
注意:如果这对任何方式都有用,我真的不感兴趣,我只想知道为什么它不能编译,因为它对我没用.
基本上,这是怎么回事:
Stage2<FuncType>::foobar<func>();
Run Code Online (Sandbox Code Playgroud)
包含一个从属名称(取决于FuncType),因此你必须遵循正确的C++ - 语法来调用成员模板(因此语法错误消息),这是
Stage2<FuncType>::template foobar<func>();
Run Code Online (Sandbox Code Playgroud)
请注意,这不适用,Stage2<void()>::foobar<func>();因为不涉及从属名称.
这同样适用Stage2<decltype(func)>::foobar<func>();,但仅此一点仍无法解决,因为存在一些棘手的障碍.根据§14.1.8[temp.param],
将类型为"T of T"或"函数返回T"的非类型模板参数分别调整为"指向T的指针"或"指向函数返回T的指针".
decltype(func)将void(*)()代替void()(即使FuncType被指定为void()),因此没有函数类型,但指向函数类型的指针将作为模板参数传递给Stage2没有提供特化的(因为Stage2<Ret (Args...)>并且Stage2<Ret (*)(Args...)>不相同),因此回退到默认模板声明,最终产生"使用不完整类型"错误.
| 归档时间: |
|
| 查看次数: |
483 次 |
| 最近记录: |