decltype(function)作为类成员

smi*_*hax 6 c++ compiler-errors linker-errors decltype c++11

我有:

int foo(int x) { return x+1; }

struct Bar {
  decltype(foo) operator();
};

int main() {
  Bar bar;
  printf("%d\n",bar(6));
}
Run Code Online (Sandbox Code Playgroud)

这会导致稍微令人吃惊的编译器错误消息(g ++ 4.6.1):

error: declaration of 'operator()' as non-function
Run Code Online (Sandbox Code Playgroud)

将成员名称更改为时

  decltype(foo) blubb;
Run Code Online (Sandbox Code Playgroud)

并使用它会导致链接器错误:

undefined reference to `Bar::blubb(int)'
Run Code Online (Sandbox Code Playgroud)

这是预期的行为吗?

Pla*_*aHH 5

您似乎想要"复制"另一个函数的签名以创建具有相同签名的函数.因为decltype(foo)确实是函数的类型(而不是指向该函数的指针decltype(&foo),它将导致指针声明),您可以使用它来声明与另一个函数具有相同签名的函数.

如链接器错误所示:

undefined reference to `Bar::blubb(int)'
Run Code Online (Sandbox Code Playgroud)

这对你的编译器已经可以正常工作了.然而,似乎gcc还没有完全实现标准的这一部分,因为它不会接受函数调用操作符的相同内容的语法.Clang btw.很乐意接受它,然后链接出错

undefined reference to `Bar::operator()(int)'
Run Code Online (Sandbox Code Playgroud)

您关于链接器错误存在的原因的问题表明对decltype真正起作用的误解.

它只会评估一种类型,而不是更多.定义与...的定义blubb无关foo.写这个时可能会更清楚

typedef decltype(foo) x; 
x blubb;
Run Code Online (Sandbox Code Playgroud)

你现在可以将typedef x显式地显式化为函数类型,它不会以任何方式改变blubb的含义.你仍然需要定义它.由于没有使用decltype定义它的语法,因此您必须明确地将其编写为

int Bar::operator()(int) {
...
}
Run Code Online (Sandbox Code Playgroud)

这很可能会遗漏使用decltype进行声明的目的/好处,因为它不允许你自动"复制"签名.