[英]How to std::bind() to create a data member?
I'm generating random values with C++11 nice new generators and distributions. 我用C ++ 11很好的新生成器和发行版生成随机值。 In a function it works like a charm and looks like this:
在一个函数中,它就像一个魅力,看起来像这样:
void foo() {
mt19937 generator;
uniform_int_distribution<unsigned> distribution;
auto dice = bind(distribution, generator);
// dice() will now give a random unsigned value
}
But how can I put all three objects in a class as data members? 但是,如何将所有三个对象作为数据成员放在一个类中呢? I can simply write
generator
and distribution
as data members, but how do I make dice
a data member without knowing (or wanting to know) its exact type? 我可以简单地将
generator
和distribution
编写为数据成员,但是如何在不知道(或想知道)其确切类型的情况下使dice
成为数据成员? Suprisingly this 这令人惊讶
class X {
mt19937 generator;
uniform_int_distribution<unsigned> distribution;
decltype(bind(distribution, generator)) dice;
};
yields the error error C2660: 'bind' : function does not take 2 arguments
in Visual Studio 2013. 产生错误
error C2660: 'bind' : function does not take 2 arguments
在Visual Studio 2013 error C2660: 'bind' : function does not take 2 arguments
。
You could always gasp write a function instead of using a lambda/bind/etc.: 你总是可以喘气写一个函数,而不是使用一个lambda /绑定的/ 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. 用于参数化生成器和/或分布类型以及使用
std::shared_ptr
保持生成器的加值点,以便您可以创建具有共享相同引擎的不同分布的多个对象。 You'll eventually want a constructor to seed the generator as well - Ideally with something like std::random_device{}()
. 你最终还是想要一个构造函数来为种子生成种子 - 理想情况下使用像
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. 对不起,我嘲笑你试图首先使用
bind
:实际上你可以用C ++ 11中的“无代码”来编写这个类。 We need to get type-inference for class member declarations in C++17 so this could be: 我们需要在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));
};
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. 鉴于最新的Concepts Lite论文建议在
auto
可能看起来意味着“推断类型,如果类型没有为命名概念建模而形成错误的语言”的任何地方使用概念名称,那么auto
成员声明可能不是不可能的。
The result of std::bind
is unspecified: this means that you cannot store its raw result without type inference. std::bind
的结果未指定:这意味着您无法在没有类型推断的情况下存储其原始结果。 However, you can use std::function
to encapsulate the result of bind
: 但是,您可以使用
std::function
来封装bind
的结果:
#include <functional>
std::function<unsigned()> dice(std::bind(distribution, generator));
auto result = dice();
EDIT: As whoever said above, this is most clearly a Visual Studio issue. 编辑:正如上面所说的那样,这显然是Visual Studio的问题。 I can confirm that this compiles with VS2013:
我可以确认这与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(); }
};
but changing the type of dice
to decltype(bind(distribution, generator))
makes the whole thing fail with flying colors (even though it still works with clang). 但是将
dice
的类型改为decltype(bind(distribution, generator))
会使整个事情失败并伴随着绚丽的色彩(即使它仍然适用于clang)。
It works on GCC . 它适用于GCC 。 I'm pretty sure that's just a compiler bug.
我很确定这只是一个编译器错误。 Unfortunately this means that you have to bite the bitter pill and use one of the workarounds described in the other answers.
不幸的是,这意味着您必须咬下苦药并使用其他答案中描述的解决方法之一。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.