我正在处理一个不实例化实例的类;它有一个受保护的构造函数,所有方法都是静态的。这个类简化了对<random>
中各种随机引擎的调用。我有一个类似的类,它对不同的分发类型做同样的事情。我对引擎的所有静态调用都能很好地工作,并且能够以多种方式为它们播种。我现在正在处理我的同伴类,以处理不同的发行版。到目前为止,我已经成功地完成了std::uniform_int
、std::uniform_int_distribution
、std::uniform_real
和std::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_int
和std::uniform_real
,因为它们只是它们各自分布的基类。
std::generate_canonical
是一个函数,而不是一个类型。