2

以下のコードを実行すると、 の前半は後半とarr等しくなります。なんで?など、さまざまなシードも試しstd::chrono::system_clock::now().time_since_epoch().count()ました。ありがとう。

#include <algorithm>
#include <iostream>
#include <random>


template<typename DistributionType>
class Rng 
{
public:
        template<typename ...Args>
        Rng(Args&&... args) : dist(args...) { } 

        typename DistributionType::result_type operator()()
        {
                return dist(gen);
        }

private:
        std::default_random_engine gen;

        DistributionType dist;
};


class UniformRealRng : public Rng<std::uniform_real_distribution<double>>
{
public:
        UniformRealRng(const double a, const double b) : Rng(a, b) { } 
};

int main()
{
        constexpr int sz = 6;
        constexpr int k  = sz / 2;
        double arr[sz];

        UniformRealRng rng(0.0, 1.0);
        std::generate(arr, arr + k, rng);
        std::generate(arr + k, arr + sz, rng);

        for (int i = 0; i < sz; ++i)
        {
                std::cout << arr[i];
        }
        std::cout << "\n";
}
4

2 に答える 2

3

std::generateは 3 番目の引数を値で受け取るため、rngコピーされていました。

安全のために、コピーを削除できます。

Rng(Rng&)             = delete;   
Rng& operator=(Rng&)  = delete;
于 2017-12-05T07:00:28.553 に答える
0

あなたの答えは事実上正しいですが、問題は解決しません。誤って (?) 乱数ジェネレーターをコピーしようとした場合にのみ、コンパイル エラーが発生します。

std::reference_wrapperライブラリの機能を使用することで、コードを意味的に正しくすることができることがわかりました。

    std::generate(arr, arr + k, std::ref(rng));
    std::generate(arr + k, arr + sz, std::ref(rng));

このようにして、基本的に引数を参照渡しすることを強制しています。 幸いなことに、リファレンス ラッパーはoperator()をオーバーロードするため、追加のコードなしでジェネレーターに使用できます。

完全なコード:

#include <algorithm>
#include <iostream>
#include <random>
#include <functional> //ref

template<typename DistributionType>
class Rng 
{
public:
        template<typename ...Args>
        Rng(Args&&... args) : dist(args...) { } 
//      Rng(Rng&)             = delete;  // this is not needed for it to work 
//      Rng& operator=(Rng&)  = delete;  // you MAY want to copy the generator
        typename DistributionType::result_type operator()()
        {
                return dist(gen);
        }

private:
        std::default_random_engine gen;

        DistributionType dist;
};


class UniformRealRng : public Rng<std::uniform_real_distribution<double>>
{
public:
        UniformRealRng(const double a, const double b) : Rng(a, b) { } 
};

int main()
{
        constexpr int sz = 6;
        constexpr int k  = sz / 2;
        double arr[sz];

        UniformRealRng rng(0.0, 1.0);
        std::generate(arr, arr + k, std::ref(rng));
        std::generate(arr + k, arr + sz, std::ref(rng));

        for (int i = 0; i < sz; ++i)
        {
                std::cout << arr[i];
        }
        std::cout << "\n";
}
于 2017-12-08T07:44:50.197 に答える