问题 匿名类可以在C ++中用作返回类型吗?


有没有办法在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.

9455
2017-11-06 11:01


起源

可能无法在返回类型中定义新类型  - 好像编译器已经回答了你的问题...... - Ed S.


答案:


注意:这些代码片段不再适用于最新版本的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

响应cheng的要求:

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 ;

5
2017-11-06 22:33



你能解释一下代码吗?这有点难以理解...... - cheng
[]() - > int {return 99;在labmda函数之前[]() - >的含义是什么? - cheng
我觉得有趣的是允许这样做,但是使用延迟返回类型的正常函数则不然。我希望在这两种情况下语法相似。 - Dennis Zickefoose
@cheng:这就是lambda函数的定义方式。 - TonyK
@TonyK: 它不起作用 g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1 - jfs


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

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

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

虽然你可以创建一个 typedef 对于一个未命名的类并将其用作返回类型,因为typedef名称成为用于链接目的的类类型的名称,该类实际上不再是匿名的。


5
2017-11-06 11:05



它仍然适用于C ++ 17吗? - innochenti


struct Test {} * a;
decltype(a) fun() {
  return a;
}

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


3
2017-11-06 11:21



decltype无法在我的环境中编译。我在linux下使用g ++(ubuntu 10.10),gcc版本是4.4.5。我已经包含了<typeinfo>头文件。 - cheng
@cheng:你不需要特殊的标题。 decltype 是c ++ 11标准的一部分。我使用当前ubuntu附带的gcc编译它。 - jfs
你的gcc版本是什么?我不确定gcc 4.4.5是否支持C ++ 11的这个功能。 - cheng
@cheng:gcc 4.6.1 - jfs
看起来您实际上可以从中删除名称 Test。 ideone.com/jjWLj - Dennis Zickefoose


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

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

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

2
2017-11-06 11:03



但这在C ++中是无用的/不必要的,并且不仅仅是命名类型更容易(可能稍微更难)。 - Karl Knechtel


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

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

?????  obj = f();

应该写什么来代替 ????? 在上面的代码?


1
2017-11-06 11:19



auto,显然:) - avakar
@avakar:那是C ++ 11。即使这样 auto 不是一种类型。 - Nawaz
例如: cout << f().x ; (请参阅我的工作代码答案。) - TonyK
@Nawaz TonyK提供了一个很好的例子 - cheng
@TonyK:那就是C ++ 11 修改 有关的任何事情 正常 功能。此外,C ++ 11 lambda(你在你的例子中使用过)是一种不同的动物。 - Nawaz


在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++;

0
2017-11-10 16:21