如何用std :: bind()创建数据成员?

时间:2014-01-08 16:58:11

标签: c++ c++11 member stdbind

我正在使用C ++ 11很好的新生成器和发行版生成随机值。在一个功能中,它就像一个魅力,看起来像这样:

void foo() {
   mt19937 generator;
   uniform_int_distribution<unsigned> distribution;
   auto dice = bind(distribution, generator);
   // dice() will now give a random unsigned value
}

但是如何将所有三个对象作为数据成员放在一个类中呢?我可以简单地将generatordistribution写为数据成员,但如何在不知道(或想知道)其确切类型的情况下使dice成为数据成员?令人惊讶的是这个

class X {
   mt19937 generator;
   uniform_int_distribution<unsigned> distribution;
   decltype(bind(distribution, generator)) dice;
};

在Visual Studio 2013中产生错误error C2660: 'bind' : function does not take 2 arguments

3 个答案:

答案 0 :(得分:7)

你总是喘气写一个函数而不是使用lambda / bind / etc.:

class X {
   mt19937 generator;
   uniform_int_distribution<unsigned> distribution;
public:
   auto dice() -> decltype(distribution(generator)) {
     return distribution(generator);
   }
   // or alternatively
   auto operator() () -> decltype(distribution(generator)) {
     return distribution(generator);
   }
};

用于参数化生成器和/或分布类型以及使用std::shared_ptr保持生成器的加值点,以便您可以创建具有共享相同引擎的不同分布的多个对象。您最终还需要一个构造函数来为发生器设定种子 - 理想情况下使用std::random_device{}()之类的东西。

或者,the answer I think you are looking for

class X {
   mt19937 generator{std::random_device{}()};
   uniform_int_distribution<unsigned> distribution{1,6};
public:
   decltype(bind(std::ref(distribution), std::ref(generator))) dice{
     bind(std::ref(distribution), std::ref(generator))
   };
};

对不起,我嘲笑你首先尝试使用bind:它实际上很简洁,你可以用#34编写这个课程;没有代码&#34 ;在C ++ 11中。我们需要在C ++ 17中获取类成员声明的类型推断,这可能是:

class X {
   auto generator = mt19937{std::random_device{}()};
   auto distribution = uniform_int_distribution<unsigned>{1,6};
public:
   auto dice = bind(std::ref(distribution), std::ref(generator));
};

鉴于the latest Concepts Lite paper建议在auto可能表示&#34;推断类型的语言中的任何地方使用概念名称,如果类型没有模型命名概念,则形式不正确,& #34; auto成员声明可能不是不可能的。

答案 1 :(得分:0)

std::bind的结果未指定:这意味着您无法在没有类型推断的情况下存储其原始结果。但是,您可以使用std::function来封装bind的结果:

#include <functional>
std::function<unsigned()> dice(std::bind(distribution, generator));
auto result = dice();

编辑:正如上面所说的那样,这显然是Visual Studio的问题。我可以确认这与VS2013编译:

#include <functional>
#include <random>

using namespace std;

class X {
    mt19937 generator;
    uniform_int_distribution<unsigned> distribution;
    std::function<unsigned()> dice;

public:
    X() : dice(bind(distribution, generator)) {}

    unsigned roll() { return dice(); }
};

但是将dice的类型更改为decltype(bind(distribution, generator))会使整个事情失败并显示绚丽的色彩(即使它仍适用于铿锵声)。

答案 2 :(得分:0)

It works on GCC。我很确定这只是一个编译器错误。不幸的是,这意味着你必须咬下苦药并使用其他答案中描述的解决方法之一。