decltype(function)作为类成员

时间:2012-02-17 10:38:54

标签: c++ compiler-errors c++11 linker-errors decltype

我有:

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

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

int main() {
  Bar bar;
  printf("%d\n",bar(6));
}

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

error: declaration of 'operator()' as non-function

将成员名称更改为

  decltype(foo) blubb;

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

undefined reference to `Bar::blubb(int)'

这是预期的行为吗?

3 个答案:

答案 0 :(得分:5)

似乎您想要“复制”另一个函数的签名以创建具有相同签名的函数。由于decltype(foo)确实是函数的类型(而不是指向该函数的指针,它将是decltype(&foo)并且将导致指针声明),因此您可以使用它来声明具有相同功能的函数签名作为另一个功能。

如链接器错误所示:

undefined reference to `Bar::blubb(int)'

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

undefined reference to `Bar::operator()(int)'

关于为什么存在链接器错误的问题表明对decltype真正起作用的误解。

它只会评估一种类型,而不是更多。 blubb的定义与foo的定义无关。在编写

时可能会更清楚
typedef decltype(foo) x; 
x blubb;

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

int Bar::operator()(int) {
...
}

很可能会遗漏使用decltype进行声明的目的/好处,因为它不允许您自动“复制”签名。

答案 1 :(得分:2)

这是一个疯狂的猜测,基于在这里观察你对printf的使用:

printf("%d\n",bar(6));

这让我假设你真的想要函数的返回类型,而不是函数的类型。如果是这样,那么您使用decltype错误。通过“模拟”函数的使用来获得函数的返回类型,即

decltype(foo(0)) operator() (int);

对你来说应该是正确的。否则,如果那不是你的注意力,你可以通过给%d说明符提供一个函数类型(而不是函数返回类型)来在冰上滑冰。

通常,decltype的含义是:decltype(@)给出表达式@的静态类型。

答案 2 :(得分:0)

这应该有效。 我只是在这里用来捕捉gobbledygook std::bind给我的任何东西:

class RiceFadingModel::Impl
{
public:
  Impl(double K, double A)
  : //...
    _M_re{system_now()},
    _M_rd{_M_nu, _M_sigma},
    _M_gen{std::bind(_M_rd, _M_re)}
  { }


private:

//...

  std::default_random_engine _M_re;
  ///  The underlying Rice distribution.
  __gnu_cxx::__rice_distribution<double> _M_rd;
  ///  The variate generator built from the pseudo-random number engine and the Rice distribution.
  decltype(std::bind(_M_rd, _M_re)) _M_gen;
};

这就像gcc-4.7上的魅力一样。现在我想起来了,我也用gcc-4.5建立了它。