我有:
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)'
这是预期的行为吗?
答案 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建立了它。