考虑以下最小示例(编译时没有 #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;
}
为什么它不能用 #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。
注意:如果这有任何用处,我真的不感兴趣,我只是想知道为什么它不能编译,因为它对我来说毫无意义。
最佳答案
基本上,发生的事情是这样的:
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],
A non-type template-parameter of type “array of T” or “function returning T” is adjusted to be of type “pointer to T” or “pointer to function returning T”, respectively.
decltype(func)
将是 void(*)()
而不是 void()
(即使 FuncType
被指定为 void()
),所以没有函数类型而是指向函数类型的指针将作为模板参数传递给 Stage2
没有提供专门化(因为 Stage2<Ret (Args...)>
和 Stage2<Ret (*)(Args...)>
不一样),因此退回到默认模板声明,最终产生“使用不完整类型”错误。
关于通过函数签名时 C++ 模板不编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46994594/