decltype(function) 作为类成员

发布于 2025-01-06 08:15:11 字数 453 浏览 0 评论 0原文

我有:

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)'

这是预期的行为吗?

I have:

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

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

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

which results in the slightly startling compiler error message (g++ 4.6.1):

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

When changing the member name to

  decltype(foo) blubb;

and using it results in a linker error:

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

Is this expected behaviour?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

南渊 2025-01-13 08:15:11

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

如链接器错误所示:

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

这已经可以在您的编译器中正常工作。然而,gcc 似乎尚未完全实现这部分标准,因为它不接受具有函数调用运算符的同一事物的语法。顺便说一句。会很高兴地接受它,然后链接会出错,并显示

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

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

它只会评估一种类型,而不是更多。 blubb 的定义与 foo 的定义没有任何关系。当这样写时,这可能会更清楚

typedef decltype(foo) x; 
x blubb;

你现在可以选择 typedef x 来显式地表示函数类型,这不会以任何方式改变 blubb 是什么。您仍然需要定义它。而且由于没有使用 decltype 定义它的语法,因此您必须明确地编写它,

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

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

It seems that you want to "copy" the signature of another function to create a function with the same signature. Since decltype(foo) is indeed the type of the function (and not a pointer to that function, which would be decltype(&foo) and would lead to a pointer declaration), you can use it to declare a function with the same signature as another function.

As indicated by the linker error:

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

this will already work fine with your compiler. However it seems that gcc did not yet fully implement this part of the standard, as it will not accept the syntax for the same thing with a function call operator. Clang btw. will happily accept it and the link then errors out with

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

Your question about why that linker error exists indicates a misunderstanding of what decltype really does.

It will just evaluate to a type, not more. The definition of blubb is in no way tied to the definition of foo. This might be clearer when writing it like

typedef decltype(foo) x; 
x blubb;

You can now alternatively typedef x to be explicitly the function type, which will not in any way change what blubb is. You still need to define it. And since there is no syntax to define it using decltype, you explicitly have to write it as

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

which will likely and unfortunately defeat the purpose/benefit of using decltype for the declaration, as it will not allow you to automatically "copy" a signature.

我不会写诗 2025-01-13 08:15:11

这是基于观察您对 printf 的使用情况的疯狂猜测:

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

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

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

应该适合您。否则,如果您没有注意到这一点,那么通过为 %d 说明符提供函数类型(而不是函数返回类型),您就会如履薄冰。

一般来说,decltype的含义是:decltype(@)给出表达式@的静态类型。

This is a wild guess based on observing your usage of printf here:

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

This lets me assume you really want the return type of the function, not the type of the function. If so, then you use decltype wrong. You get the return type of the function by "simulating" the usage of the function, i.e.

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

should be the right thing for you. Otherwise, if that was not your attention, you are skating on thin ice by giving a function type (and not function return type) to the %d specifier.

Generally, the meaning of decltype is: decltype(@) gives the static type of the expression @.

自我难过 2025-01-13 08:15:11

这应该有效。
我只是在这里用它来捕获 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 上就像一个魅力。现在我想起来了,我也在 mingw 上用 gcc-4.5 构建了它。

This should work.
I just used it here to capture whatever gobbledygook std::bind was going to give me:

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;
};

This works like a charm on gcc-4.7. Now that I think about it I built it on mingw with gcc-4.5 too.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文