为什么我不能在C++0x的Lambda函数中声明结构体变量?

3
这是代码。
#include<struct.h>
#include<iostream>
#include<functional>
using namespace std;

void LambdaTest(const function <struct dummy (void)>& f)
    {
    struct dummy test = f();
    cout<<test.a<<endl;
    }

int main()
    {
    int val = 5;
    struct dummy dum;

    auto func = [val](void) -> struct dummy
                        {
                        dummy temp;
                        temp.a = val;
                        return temp;
                        };

    LambdaTest(func);
    return 0;
    }

文件struct.h非常简单。
struct dummy
    {
    int a;
    };

GCC报错:

lambda_struct.cpp:19:38: 错误:字段 'temp' 具有不完整的类型

这样允许吗?如果是,怎么修复它?如果不是,为什么?

编辑:

代码中发现了返回类型的错误(由他人发现),已经进行了修复。

解决方法:

问题在于C++0x标准允许在lambda函数定义本身的返回类型中定义一个新的struct(和class也一样),所以如果返回类型中存在struct关键字,编译器将认为它是一个新类型并开始抱怨。

修复后的代码如下:

#include<struct.h>
#include<iostream>
#include<functional>
using namespace std;

void LambdaTest(const function <struct dummy (void)>& f)
    {
    struct dummy test = f();
    cout<<test.a<<endl;
    }

int main()
    {
    int val = 5;
    struct dummy dum;

    auto func = [val](void) -> dummy
                        {
                        dummy temp;
                        temp.a = val;
                        return temp;
                        };

    LambdaTest(func);
    return 0;
    }

我在MSVC++中遇到了错误,提示你的lambda表达式没有返回值。`anonymous namespace'::<lambda0>::operator()' : must return a value. 修复后,程序成功编译并输出了5。 - 0x5f3759df
3个回答

7
问题在于GCC错误地认为您正在声明一个新的结构体类型,而它声明了一个不完整类型的字段,该类型与GCC认为您正在声明的类型相同。
它还抱怨说,在赋值语句那一行,
error: 'temp'未命名类型
因为它期望成员声明而不是语句。
更改为:
auto func = [val](void) -> dummy
                        {
                            struct dummy temp;
                            temp.a = val;
                            return temp;
                        };

会工作。

此外,请注意,不从函数返回值可能会导致未定义的行为。


这个答案是不正确的。你不能在尾随返回类型中定义一个结构体,这只是一个g++的错误。 - Richard Smith

0
如果你去掉struct部分,只是正常定义变量会发生什么?你知道,就像这样:
dummy temp;

此外,尝试摆脱lambda返回值中的其他多余struct。顺便提一下,你需要实际返回temp才能编译成功。

1
令人惊讶的是,GCC(ideone)甚至没有对lambda中缺少的返回语句发出警告。它愉快地在LambdaTest()中打印出垃圾。 - Praetorian

0
在C++中,与C不同的是,结构体不会被放置在单独的命名空间中,因此您不必在每个声明中使用关键字struct。此外,您的代码存在错误,lambda函数需要返回一个dummy类型的实例。以下代码编译并按预期运行:
#include<iostream>
#include<functional>
using namespace std;

struct dummy
    {
    int a;
    };

void LambdaTest(const function <dummy (void)>& f)
    {
    dummy test = f();
    cout<<test.a<<endl;
    }

int main()
    {
    int val = 5;
    dummy dum;

    auto func = [val](void) -> dummy
                        {
                        dummy temp;
                        temp.a = val;
                        return temp; // return the temp struct
                        };

    LambdaTest(func);
    return 0;
    }

输出:

5


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接