在类接口内的模板化静态方法中使用std::generator_canonical



我正在处理一个不实例化实例的类;它有一个受保护的构造函数,所有方法都是静态的。这个类简化了对<random>中各种随机引擎的调用。我有一个类似的类,它对不同的分发类型做同样的事情。我对引擎的所有静态调用都能很好地工作,并且能够以多种方式为它们播种。我现在正在处理我的同伴类,以处理不同的发行版。到目前为止,我已经成功地完成了std::uniform_intstd::uniform_int_distributionstd::uniform_realstd::uniform_real_distribution。现在我已经开始使用std::generate_canonical了,我开始遇到编译器错误。

这就是我的RandomGenerator头文件的样子:

#ifndef RANDOM_GENERATOR_H
#define RANDOM_GENERATOR_H
#include <chrono>
#include <random>
class RandomEngine {
public:
    using Clock = std::conditional_t<std::chrono::high_resolution_clock::is_steady,
        std::chrono::high_resolution_clock,
        std::chrono::steady_clock>;
    // Used To Determine Which Seeding Process To Use
    enum SeedType {
        USE_CHRONO_CLOCK,
        USE_RANDOM_DEVICE,
        USE_SEED_VALUE, 
        USE_SEED_SEQ,
    }; // SeedType
    // This Enum Is Not In Use - It Is A Visual Reference Only; But If User Wants To
    // Use It For Their Own Pupose They Are Free To Do So.
    enum EngineType {
        // Default Random Engine
        DEFAULT_RANDOM_ENGINE,
        // Linear Congruential Engines
        MINSTD_RAND0,
        MINSTD_RAND,
        // Mersenne Twister Engines 
        MT19937,
        MT19937_64,
        // Subtract With Carry Engines 
        RANLUX24_BASE,
        RANLUX48_BASE,
        // Discard Block Engines 
        RANLUX24,
        RANLUX48,
        // Shuffle Order Engines
        KNUTH_B,
    }; // EngineType
protected:
    RandomEngine(){}
public:
    static unsigned int getTimeNow() {
        unsigned int now = static_cast<unsigned int>(Clock::now().time_since_epoch().count());
        return now;
    } // getTimeNow
    static std::random_device& getRandomDevice() {
        static std::random_device device{};
        return device;
    } // getRandomDevice
    static std::default_random_engine& getDefaultRandom( SeedType type, unsigned seedValue = 0, std::seed_seq& seq = std::seed_seq{} ) {
        static std::default_random_engine engine{};
        if ( type == USE_RANDOM_DEVICE ) {
            engine.seed( getRandomDevice()() );
        }
        if ( type == USE_CHRONO_CLOCK ) {
            engine.seed( getTimeNow() );
        }
        if ( type == USE_SEED_VALUE ) {
            engine.seed( seedValue );
        }
        if ( type == USE_SEED_SEQ ) {
            engine.seed( seq );
        }
        return engine;
    } // getDefaultEngine
    static std::minstd_rand0& getMinStd_Rand0( SeedType type, unsigned seedValue = 0 ) {
        static std::minstd_rand0 engine{};
        if ( type == USE_RANDOM_DEVICE ) {
            engine.seed( getRandomDevice()() );
        }
        if ( type == USE_CHRONO_CLOCK ) {
            engine.seed( getTimeNow() );
        }
        if ( type == USE_SEED_VALUE ) {
            engine.seed( seedValue );
        }
        return engine;
    } // getMinStd_Rand0
    static std::minstd_rand& getMinStd_Rand( SeedType type, unsigned seedValue = 0 ) {
        static std::minstd_rand engine{};
        if ( type == USE_RANDOM_DEVICE ) {
            engine.seed( getRandomDevice()() );
        }
        if ( type == USE_CHRONO_CLOCK ) {
            engine.seed( getTimeNow() );
        }
        if ( type == USE_SEED_VALUE ) {
            engine.seed( seedValue );
        }
        return engine;
    } // getMinStd_Rand
    static std::mt19937& getMt19937( SeedType type, unsigned seedValue = 0 ) {
        static std::mt19937 engine{};
        if ( type == USE_RANDOM_DEVICE ) {
            engine.seed( getRandomDevice()() );
        }
        if ( type == USE_CHRONO_CLOCK ) {
            engine.seed( getTimeNow() );
        }
        if (type == USE_SEED_VALUE) {
            engine.seed( seedValue );
        }
        return engine;
    } //getMt19937
    static std::mt19937_64& getMt19937_64( SeedType type, unsigned seedValue = 0 ) {
        static std::mt19937_64 engine{};
        if (type == USE_RANDOM_DEVICE) {
            engine.seed(getRandomDevice()());
        }
        if (type == USE_CHRONO_CLOCK) {
            engine.seed(getTimeNow());
        }
        if (type == USE_SEED_VALUE) {
            engine.seed(seedValue);
        }
        return engine;
    } // getMt19937_64
    static std::ranlux24_base& getRanLux24_base( SeedType type, unsigned seedValue = 0 ) {
        static std::ranlux24_base engine{};
        if ( type == USE_RANDOM_DEVICE ) {
            engine.seed( getRandomDevice()() );
        }
        if ( type == USE_CHRONO_CLOCK ) {
            engine.seed( getTimeNow() );
        }
        if ( type == USE_SEED_VALUE ) {
            engine.seed( seedValue );
        }
        return engine;
    } // getRanLux24_base
    static std::ranlux48_base& getRanLux48_base( SeedType type, unsigned seedValue = 0 ) {
        static std::ranlux48_base engine{};
        if ( type == USE_RANDOM_DEVICE ) {
            engine.seed( getRandomDevice()() );
        }
        if ( type == USE_CHRONO_CLOCK ) {
            engine.seed( getTimeNow() );
        }
        if ( type == USE_SEED_VALUE ) {
            engine.seed( seedValue );
        }
        return engine;
    } // getRanLux48_base
    static std::ranlux24& getRanLux24( SeedType type, unsigned seedValue = 0 ) {
        static std::ranlux24 engine{};
        if ( type == USE_RANDOM_DEVICE ) {
            engine.seed( getRandomDevice()() );
        }
        if ( type == USE_CHRONO_CLOCK ) {
            engine.seed( getTimeNow() );
        }
        if ( type == USE_SEED_VALUE ) {
            engine.seed( seedValue );
        }
        return engine;
    } // getRanLux24
    static std::ranlux48& getRanLux48( SeedType type, unsigned seedValue = 0 ) {
        static std::ranlux48 engine{};
        if ( type == USE_RANDOM_DEVICE ) {
            engine.seed( getRandomDevice()() );
        }
        if ( type == USE_CHRONO_CLOCK ) {
            engine.seed( getTimeNow() );
        }
        if ( type == USE_SEED_VALUE ) {
            engine.seed( seedValue );
        }
        return engine;
    } //getRanLux48
}; // RandomEngine
class RandomDistribution {
public:
    // This Enum Is Not In Use - It Is A Visual Reference Only; But If User Wants To
    // Use It For Their Own Pupose They Are Free To Do So.
    enum DistributionType {
        // Uniform Distributions
        UNIFORM_INT,
        UNIFORM_INT_DISTRIBUTION,
        UNIFORM_REAL,
        UNIFORM_REAL_DISTRIBUTION,
        GENERATE_CANONICAL,
        // Bernoulli Distributions
        BERNOULLI_DISTRIBUTION,
        BINOMAIL_DISTRIBUTION,
        NEGATIVE_BINOMIAL_DISTRIBUTION,
        GEOMETRIC_DISTRIBUTION,
        // Poisson Distributions
        POISSON_DISTRIBUTION,
        EXPONENTIAL_DISTRIBUTION,
        GAMMA_DISTRIBUTION,
        WEIBULL_DISTRIBUTION,
        EXTREME_VALUE_DISTRIBUTION,
        // Normal Distributions
        NORMAL_DISTRIBUTION,
        LOGNORMAL_DISTRIBUTION,
        CHI_SQUARED_DISTRIBUTION,
        CAUCHY_DISTRIBUTION,
        FISHER_F_DISTRIBUTION,
        STUDENT_T_DISTRIBUTION,
        // Sampling Distributions
        DISCRETE_DISTRIBUTION,
        PIECEWISE_CONSTANT_DISTRIBUTION,
        PIECEWISE_LINEAR_DISTRIBUTION
    }; // DistributionType
protected:
    RandomDistribution(){}
public:
    template<class IntType = int>
    static std::uniform_int<IntType>& getUniformInt( IntType lowerBound, IntType upperBound ) {
        static std::uniform_int<IntType> dist( lowerBound, upperBound );
        return dist;
    } // getUniformInt
    template<class IntType = int>
    static std::uniform_int<IntType>& getUniformIntDistribution( IntType lowerBound, IntType upperBound ) {
        static std::uniform_int_distribution<IntType> dist( lowerBound, upperBound );
        return dist;
    } // getUniformIntDistribution
    template<class RealType = double>
    static std::uniform_real<RealType>& getUniformReal( RealType lowerBound, RealType upperBound ) {
        static std::uniform_real<RealType> dist( lowerBound, uppperBound );
        return dist;
    } // getUniformReal
    template<class RealType = double>
    static std::uniform_real_distribution<RealType>& getUniformRealDistribution( RealType lowerBound, RealType upperBound ) {
        static std::uniform_real_distribution<RealType> dist( lowerBound, upperBound );
        return dist;
    } // getUniformRealDistribution
    template<class RealType = double, std::size_t numBits, class Generator>
    static std::generate_canonical<RealType, numBits>& getGenerateCanonical( Generator& engine ) {
        static std::generate_canonical<RealType, numBits> dist( engine );
        return dist;
    } // getGeneratorCanonical    
}; // RandomDistribution
typedef RandomEngine RE;
typedef RandomDistribution RD;
// #include "RandomGeneator.inl"
#endif // RANDOM_GENERATOR_H

我正在研究的就是这个功能

    template<class RealType = double, std::size_t numBits, class Generator>
    static std::generate_canonical<RealType, numBits>& getGenerateCanonical( Generator& engine ) {
        static std::generate_canonical<RealType, numBits> dist( engine );
        return dist;
    } // getGeneratorCanonical 

我一直在遵循这个网站的语法形式:cppreference,他们有这行代码

std::cout << std::generate_canonical<double, 10>(gen) << ' ';

我正在尝试创建并返回此分发版的静态实例。模板参数中的RealType默认为double,最好与std::generate_canonical一起使用,std::size_t是第二个模板参数的字段中的位数,第三个模板参数表示要传递给它的RandomEngine生成器。但是,我在正确定义此函数时遇到了问题。我不断收到来自VS2015 的编译器错误

1>------ Build started: Project: DieRoll, Configuration: Debug Win32 ------
1>  RandomGenerator.cpp
1>c:usersskilz80documentsvisual studio 2015projectsdierolldierollrandomgenerator.h(297): error C2988: unrecognizable template declaration/definition
1>c:usersskilz80documentsvisual studio 2015projectsdierolldierollrandomgenerator.h(297): error C2143: syntax error: missing ';' before '&'
1>c:usersskilz80documentsvisual studio 2015projectsdierolldierollrandomgenerator.h(297): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:usersskilz80documentsvisual studio 2015projectsdierolldierollrandomgenerator.h(297): error C2365: 'std::generate_canonical': redefinition; previous definition was 'function'
1>  c:program files (x86)microsoft visual studio 14.0vcincluderandom(295): note: see declaration of 'std::generate_canonical'
1>c:usersskilz80documentsvisual studio 2015projectsdierolldierollrandomgenerator.h(297): error C2238: unexpected token(s) preceding ';'
1>c:usersskilz80documentsvisual studio 2015projectsdierolldierollrandomgenerator.h(297): error C2059: syntax error: '&'
1>c:usersskilz80documentsvisual studio 2015projectsdierolldierollrandomgenerator.h(304): error C2143: syntax error: missing ';' before '}'
1>c:usersskilz80documentsvisual studio 2015projectsdierolldierollrandomgenerator.h(304): error C2238: unexpected token(s) preceding ';'
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

我尝试过其他方法来定义它,但我也遇到了类似的错误。我不需要这些函数来完成由用户定义的实际工作,我只是创建一个简单的用户界面,以便快速方便地访问,以创建一个准备好的RandomEngine和一个PreparedDistribution,其中一个实例是静态生成的,但用户仍然可以选择创建所使用类型的本地变量。任何关于如何正确构造此静态函数的建议都将不胜感激。

EDIT感谢ildjarn,他提到std::generate_canonical是一个函数,而不是类模板。当我回到我引用的网站时,他们确实用绿色小文本将其列为函数模板,而不是类模板。现在我直接知道了它是什么,我可以从我的类中省略它,而不用担心它。这现在消除了我无法编译它时的一些困惑。

编辑

我终于完成了我的课程,合并了所有主要的发行版,并对它们进行了测试,它们似乎都能正常工作。我还删除了std::uniform_intstd::uniform_real,因为它们只是它们各自分布的基类。

std::generate_canonical是一个函数,而不是一个类型。

相关内容

  • 没有找到相关文章

最新更新