5

我正在使用 C++11 不错的新生成器和分布生成随机值。在一个函数中,它就像一个魅力,看起来像这样:

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

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

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

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

4

3 回答 3

7

You could always gasp write a function instead of using a 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);
   }
};

Bonus points for parameterizing on the type of the generator and/or distribution, and for holding the generator with a std::shared_ptr so that you can make several objects with differing distributions that share the same engine. You'll eventually want a constructor to seed the generator as well - Ideally with something like std::random_device{}().

Or, 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))
   };
};

I'm sorry I mocked you for trying to use bind in the first place: it's actually kind of neat that you can write this class with "no code" in C++11. We need to get type-inference for class member declarations in C++17 so this could be:

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));
};

Given that the latest Concepts Lite paper proposes using concept names anywhere in the language where auto can appear to mean "infer type, ill-formed if type doesn't model named concept," auto member declarations may not be out of the question.

于 2014-01-08T17:04:43.533 回答
0

它适用于 GCC。我很确定这只是一个编译器错误。不幸的是,这意味着您必须吃苦头并使用其他答案中描述的解决方法之一。

于 2014-01-08T17:21:11.983 回答
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(); }
};

但是将类型更改dicedecltype(bind(distribution, generator))会使整个事情失败(即使它仍然适用于clang)。

于 2014-01-08T17:15:23.903 回答