代码之家  ›  专栏  ›  技术社区  ›  doraemon

无法按值捕获随机引擎

  •  2
  • doraemon  · 技术社区  · 7 年前

    我的代码不能被gcc 8编译,但我不明白为什么。

    #include <iostream>
    #include <algorithm>
    #include <random>
    using namespace std;
    
    template<class... T>
    void diagnose(T... x);
    
    int main()
    {
        auto d = normal_distribution<double>(0.0, 1.0);
        auto g = default_random_engine();
        cout << d(g) << endl;
        auto gen = [=](){
            //diagnose(d, g);
            return d(g);   // ******
        };
        cout << gen() << endl;
    }
    

    错误信息显示(指向 ******* ):

    error: no match for call to ‘(const std::normal_distribution<double>) (const std::linear_congruential_engine<long unsigned int, 16807, 0, 2147483647>&)
    

    但是,如果我将捕获更改为引用捕获,则代码可以工作。

    如果我取消注释 //diagnose 行,错误消息如下(还需要更改 return d(g) return 1.0 ):

    undefined reference to `void diagnose<std::normal_distribution<double>, std::linear_congruential_engine<unsigned long, 16807ul, 0ul, 2147483647ul> >(std::normal_distribution<double>, std::linear_congruential_engine<unsigned long, 16807ul, 0ul, 2147483647ul>)'
    

    如您所见,在按值捕获的情况下,参数 g 是常量引用。但是 const 不出现在诊断中。

    有人能解释一下这是怎么回事吗?

    1 回复  |  直到 7 年前
        1
  •  3
  •   rafix07    7 年前

    你路过 d 按价值 [=] 所以这个对象的副本是在lambda中创建的,但是lambda函数的主体是 const 所以你不能改变lambda体中的对象。 normal_distribution::operator() 成员不是常量。在const成员中,只能为成员对象调用const方法。您可以通过向lambda添加mutable来解决这个问题

     auto gen = [=]() mutable {
        //diagnose(d, g);
        return d(g);   // ******
    };
    

    或通过 通过引用

     auto gen = [&](){
            //diagnose(d, g);
            return d(g);   // ******
        };