【问题标题】:Type deduction for variable declared in lambda's capture在 lambda 的捕获中声明的变量的类型推导
【发布时间】:2020-02-20 15:22:21
【问题描述】:

在这个 sn-p 中,我在 lambda 的捕获中声明了一个变量 i

int main()
{
    vector<int> vec;

    // Pushing 0-99 numbers to vector
    std::generate_n(std::back_inserter(vec), 100, [i = 0]() mutable { return i++; });

    return 0;
}

正如大家所见,i 没有任何类型。

据我所知,可以这样写等效功能:

int main()
{
    vector<int> vec;

    // Pushing 0-99 numbers to vector
    std::generate_n(std::back_inserter(vec), 100, [](){
             static int i = 0; 
             return i++; });

    return 0;
}

编译器是如何知道第一个例子中i的类型的?是不是我对它的操作推导出来的(++)?是不是因为容器知道是int

使用 -std=c++14 和 -std=c++17 编译 GCC 时没有任何问题。 不过,如果我使用 -std=c++11 进行编译,我会收到以下警告:

lambda_test.cpp: In function ‘int main()’:
lambda_test.cpp:24:51: warning: lambda capture initializers only available with -std=c++14 or -std=gnu++14
  std::generate_n(std::back_inserter(first), 100, [i = 0]() mutable { return i++; });
                                                   ^

MORE:考虑到 cmets,我尝试查看编译器为 c++11 和 14 生成的内容的差异,但它生成的代码相同: https://cppinsights.io/s/43411e6f

【问题讨论】:

    标签: c++ lambda capture type-deduction


    【解决方案1】:

    正如错误所说,您必须激活 C++14 才能使 lambda 捕获初始化程序工作,因为它是在 C++14 中添加的。

    据我所知,可以这样写等效功能:

    不,静态存储在功能上有所不同。使用捕获,您可以复制 lambda,它将复制捕获的状态。使用静态变量,每个 lambda 访问相同的全局变量。

    编译器如何知道第一个例子中 i 的类型? 是从我对它执行的操作推导出来的(++)吗?是不是因为容器才知道是int?

    不,因为很多类型都有 ++ 运算符。

    编译器只是使用初始化器来推断类型。你可以看到那里好像有一个隐藏的auto

    std::generate_n(std::back_inserter(vec), 100, [/* auto */ i = 0]() mutable { return i++; });
    

    文字0 的类型为int。所以iint

    从技术上讲,您也可以这样做:

    std::generate_n(std::back_inserter(vec), 100, [/* auto */ i = 0ull]() mutable { return i++; });
    

    那么i 的类型为unsigned long long,因为文字0ull 属于该类型。

    【讨论】:

    • 如果它是在 c++14 中添加的,为什么它仍然为 -std=c++11 编译?它也运行良好。
    • @danigezad 也许你的编译器接受它作为 c++11 的扩展并警告而不是报告错误。在 C++03 时代,启用 C++0x 功能作为扩展是很常见的
    【解决方案2】:

    它就像你做的那样工作

    auto i = 0;
    

    如果您没有捕获现有变量,则必须指定一个初始化程序,并且该初始化程序用于确定类型。

    【讨论】:

      猜你喜欢
      • 2019-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-12
      相关资源
      最近更新 更多