【问题标题】:Can anonymous class be used as return types in C++?匿名类可以用作 C++ 中的返回类型吗?
【发布时间】:2011-11-06 11:01:17
【问题描述】:

有没有办法在 C++ 中使用匿名类作为返回类型?

我在谷歌上搜索过这可能有效:

struct Test {} * fun()
{
}

但是这段代码没有编译,错误信息是:

新类型不能在返回类型中定义

其实这段代码没有任何意义,我只是想弄清楚在C++中是否可以使用匿名类作为返回类型。

这是我的代码:

#include <typeinfo>
#include <iterator>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdlib>

using namespace std;

int main(int argc, char **argv)
{
    int mx = [] () -> struct { int x, y ; } { return { 99, 101 } ; } ().x ;
    return 0;
}

我用 g++ xx.cpp -std=c++0x 编译这段代码,编译器比较:

expected primary-expression before '[' token.

【问题讨论】:

  • 新类型可能没有在返回类型中定义 - 好像编译器已经回答了你的问题......

标签: c++ anonymous-types anonymous-class


【解决方案1】:

注意:这些代码 sn-ps 不再适用于最新版本的 g++。我用 4.5.2 版本编译它们,但 4.6.1 和 4.7.0 版本不再接受它们。


可以将匿名结构声明为 C++11 中 lambda 函数的返回类型。但这并不漂亮。此代码将值 99 分配给 mx

int mx = [] () -> struct { int x, y ; } { return { 99, 101 } ; } ().x ;

ideone 输出在这里:http://ideone.com/2rbfM

应郑的要求:

lambda 函数是 C++11 中的一个新特性。它基本上是一个匿名函数。这是一个更简单的 lambda 函数示例,它不接受任何参数并返回 int

[] () -> int { return 99 ; }

您可以将其分配给一个变量(您必须使用auto 来执行此操作):

auto f = [] () -> int { return 99 ; } ;

现在你可以这样称呼它:

int mx = f() ;

或者你可以直接调用它(这是我的代码所做的):

int mx = [] () -> int { return 99 ; } () ;

我的代码只是使用struct { int x, y ; } 代替int。末尾的.x 是应用于函数返回值的普通struct 成员语法。

此功能并不像看起来那么无用。您可以多次调用该函数,以访问不同的成员:

auto f = [] () -> struct {int x, y ; } { return { 99, 101 } ; } ;
cout << f().x << endl ;
cout << f().y << endl ;

您甚至不必调用该函数两次。此代码完全符合 OP 的要求:

auto f = [] () -> struct {int x, y ; } { return { 99, 101 } ; } () ;
cout << f.x << endl ;
cout << f.y << endl ;

【讨论】:

  • [] () -> int { 返回 99 ; labmda函数前的[]()->是什么意思?
  • 我发现这是允许的,但对于使用延迟返回类型的普通函数来说,这是不允许的。我本来希望这两种情况下的语法是相似的。
  • @cheng:这就是 lambda 函数的定义方式。
  • @TonyK 你编译代码了吗? int mx = [] () -> struct { int x, y ; } { 返回 { 99, 101 } ; } ()。X ;此行在我的环境下无法编译:g++ 4.4.5 and ubuntu 10.10
【解决方案2】:

不是他们不能。如错误消息中所示,来自 ISO/IEC 14882:2011 8.3.5/9:

类型不应在返回或参数类型中定义。函数定义的参数类型或返回类型不应是不完整的类类型(可能是 cv 限定的),除非函数定义嵌套在该类的成员规范中(包括在该类中定义的嵌套类中的定义) )。

当然,您不能在函数声明中将现有匿名类型命名为返回类型,因为匿名类没有名称。

虽然您可以为未命名的类创建 typedef 并将其用作返回类型,但由于 typedef 名称成为用于链接目的的类类型的名称,该类不再是真正的匿名类了。

【讨论】:

  • C++17 仍然如此吗?
【解决方案3】:
struct Test {} * a;
decltype(a) fun() {
  return a;
}

顺便说一句,struct Test {} 不是匿名结构。

【讨论】:

  • decltype 在我的环境中无法编译。我在linux(ubuntu 10.10)下使用g++,gcc版本是4.4.5。我已经包含了 头文件。
  • @cheng:您不需要特殊的标题。 decltype 是 c++11 标准的一部分。我使用当前 ubuntu 附带的 gcc 编译它。
  • 你的 gcc 版本是多少?我不确定 gcc 4.4.5 是否支持 C++ 11 的这个特性。
  • 看起来您实际上可以从Test 中删除名称。 ideone.com/jjWLj
  • @J.F.塞巴斯蒂安 谢谢你的帮助。我使用以下代码编译此代码:g++ xx.cpp -std=c++0x
【解决方案4】:

不,你不能在 C++ 中做这样的匿名类型。

但是,您可以使用 typedef 为匿名类型分配新名称。

typedef struct
{
    unsigned x;
    unsigned y;
} TPoint;

【讨论】:

  • 但这在 C++ 中是无用的/不必要的,而且并不比仅仅命名类型更容易(可以说稍微难一点)。
【解决方案5】:

在 C++14 中,你能得到的最接近你想要的东西是这样的:

auto f() { 
    struct {
        int x, y;
    } ret{10,24};
    return ret;
}
int main() {
  printf("%i", f().x);
}

结构是匿名的(ret 是变量名,不是类型名),并被返回。

如果需要,您仍然可以使用

using my_struct = decltype(f());
my_struct another; another.x++;

【讨论】:

    【解决方案6】:

    @Charles 的帖子几乎回答了直接引用规范的问题。

    现在,我想为什么 anonymous 类型不能是函数的返回类型,是因为假设 f 返回一个匿名类型,那么在调用站点会写什么?

    ?????  obj = f();
    

    上面代码中的?????应该写什么?

    【讨论】:

    • @avakar:那是 C++11。即使那样auto 也不是类型。
    • 例如:cout &lt;&lt; f().x ;(查看我的工作代码答案。)
    • @TonyK:那是 C++11,它不会修改任何与 normal 函数有关的东西。此外,C++11 lambda(您在示例中使用过)是另一种动物。
    • @cheng:阅读以上评论
    • @Nawaz:现在你太虚伪了!您声称一个函数不能返回匿名类型,因为那样它将无法使用,对吗?如果可能的话,我将向您展示它如何 可用(不使用 lambda 或 C++11 中的任何东西)。就像f().x 一样简单。
    猜你喜欢
    • 2012-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多