2

std::discrete_distributionクラス コンストラクターに渡されたデータを使用してオブジェクトを作成しようとしています。静的データを使用してこれを作成する方法は知っていますが、変数データを (きれいに) 使用する方法を理解できません。私が今持っているものは「機能」していますが、痛いです。これを行うより適切な方法はありますか?

distInit = { distArray[0], ... };ラインが問題です。

#include <iostream>
#include <iomanip>
#include <initializer_list>
#include <map>
#include <random>

class Die {
    private:
        int loadSide;
        double loadAmount;
        std::mt19937 generator;
        std::discrete_distribution<> distribution;
        std::initializer_list<double> distInit;
        std::array<double, 7> distArray;
    public:
        Die( int loadSide, double loadAmount ) : loadSide(loadSide), loadAmount(loadAmount) {
            distArray.fill( 1 );
            distArray[0] = 0;
            distArray[this->loadSide] = this->loadAmount;

            distInit = { distArray[0], distArray[1], distArray[2], distArray[3], distArray[4], distArray[5], distArray[6] };
            distribution.param( distInit );
        };
        int roll( ) {
                return distribution( generator );
        };
};

const int ROUNDS = 10000;

int main() {
    Die* die = new Die( 5, 20 );

    std::map<int, int> m;
    for(int n=0; n < ROUNDS; n++) {
        m[die->roll()]++;
    }
    for(auto p : m) {
        std::cout << p.first << " generated " << std::setiosflags(std::ios::fixed) << std::setprecision(2) << (float) p.second / ROUNDS << " times\n";
    }
}

適切な質問をしていない可能性があります。その場合は事前にお詫び申し上げます。これは可能性が高いです。なぜなら、この件に関する (明らかに) 関連するヒットが見つからないことに驚いているからです。

私のコンパイラはg++-mp-4.8 (MacPorts gcc48 4.8-20130411_0) 4.8.1 20130411 (prerelease)

コマンドライン/opt/local/bin/g++-mp-4.8 -std=c++11 test.cpp -o test

4

3 に答える 3

2

std::initializer_list一時オブジェクト (関数の引数) またはローカル変数としての使用のみを目的としています。これはコンテナではなく、何も所有していません。これは、匿名の一時配列へのアクセサーです。

標準には、あなたのコードに似た例、§8.5.4/6 が含まれています。

initializer_list オブジェクトはコンストラクターの ctor-initializer で初期化されるため、配列はコンストラクターが終了するまでのみ存続し、コンストラクターが終了した後に i4 の要素を使用すると、未定義の動作が発生します。

あなたの場合、それはコンストラクターの本体であり、本体の前にある ctor-initializer ではありませんが、ストーリーは同じです。あなたのプログラムが今のところうまくいっているのは、運が悪いだけです。

分布をオブジェクトに格納するには、std::arrayまたはを使用しますstd::vectorarrayより効率的ですが、arr = { … }構文をサポートしていません。(いくつかの簡単な代替手段があります。)vector中括弧と=演算子を使用した構文をサポートします。このサポートは暗黙的な を使用しstd::initializer_listます。

于 2013-05-03T04:14:01.517 に答える
2

変数データが​​ある場合はdiscrete_distribution、イテレータのペアを取るコンストラクタを使用する必要があります。

template< class InputIt >
discrete_distribution( InputIt first, InputIt last );

param_typeを直接構築しようとするべきではありません。代わりに、ヘルパー関数を使用してディストリビューションを構築します。

class Die {
    private:
        std::mt19937 generator;
        std::discrete_distribution<> distribution;
        static std::discrete_distribution<> makeDistribution(
            int loadSide, double loadAmount )
        {
            std::array<double, 7> distArray;
            distArray.fill( 1 );
            distArray[0] = 0;
            distArray[loadSide] = loadAmount;
            return {std::begin(distArray), std::end(distArray)};
        }
    public:
        Die( int loadSide, double loadAmount ) :
            generator{ },
            distribution{ makeDistribution( loadSide, loadAmount ) }
        {}
        int roll( ) {
                return distribution( generator );
        }
};
于 2013-05-03T09:32:05.070 に答える
0

OPに示されているもの以外のstd::initializer_listようなコンテナからを作成するより良い方法はわかりません。std::array

ただし、元の問題、つまりパラメーターをディストリビューションに渡すことについては、もっと簡単なことを提案できます。

    typedef std::discrete_distribution<>::param_type param_type;
    distribution.param(param_type(distArray.begin(), distArray.end()));

標準では、ディストリビューションは型メンバーparam_type( が受け取る引数の型) を提供する必要があると述べてparam()いますが、それを指定していません。ただし、 [rand.req.dist] は、

分布のパラメーターに対応する引数をとる D [分布型] の各コンストラクターに対して、P [param_type] は、同じ要件に従い、数、型、およびデフォルト値が同一の引数をとる対応するコンストラクターを持たなければなりません。

std::discrete_distribution<>パラメーターの範囲を指すイテレーターを取るコンストラクターがあることがわかりました。したがって、それが何であれstd::discrete_distribution<>::param_type、同様のコンストラクターが必要です。param_typeしたがって、 fromdistArray.begin()を作成しdistArray.end()て に渡すことをお勧めしdistribution.param()ます。

std::initializer_list<double> distInit;補足:クラスではもう必要ありません。クラスメンバーとしても必要ないように思えます(のコンストラクターのstd::array<double, 7> distArrayローカル変数である可能性があります)。Die

于 2013-05-03T04:04:07.240 に答える