简体   繁体   English

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

[英]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? 我可以简单地将generatordistribution编写为数据成员,但是如何在不知道(或想知道)其确切类型的情况下使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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM