Я попробовал две вещи:C++: шаблон класса против двух классов: эффективность
class RandDouble{
public:
RandDouble(double const& min_inclusive, double const& max_exclusive):
mt_(std::random_device()),
dist_(min_inclusive,max_exclusive)
{}
~RandDouble(){}
double get(){ return dist_(mt_); }
private:
std::mt19937_64 mt_;
std::uniform_real_distribution<double> dist_;
};
class RandUnsignedInt{
public:
RandUnsignedInt(unsigned int const& min_inclusive, unsigned int const& max_inclusive):
mt_(std::random_device()),
dist_(min_inclusive,max_exclusive)
{}
~RandUnsignedInt(){}
unsigned int get(){ return dist_(mt_); }
private:
std::mt19937_64 mt_;
std::uniform_int_distribution<unsigned int> dist_;
};
И
template<typename Type>
class Rand{
public:
Rand(Type const& min_inclusive, Type const& max_exclusive);/
~Rand();
Type get();
private:
std::mt19937_64 mt_;
std::uniform_real_distribution<double>* dist_double_;
std::uniform_int_distribution<unsigned int>* dist_u_int_;
};
template<typename Type>
Rand<Type>::~Rand(){
if(dist_double_){ delete dist_double_; }
if(dist_u_int_){ delete dist_u_int_; }
}
с файлом .cpp
:
template<>
Rand<double>::Rand(double const& min_inclusive, double const& max_exclusive):
mt_(std::random_device()()),
dist_double_(new std::uniform_real_distribution<double>(min_inclusive,max_exclusive)),
dist_u_int_(NULL)
{}
template<>
Rand<unsigned int>::Rand(unsigned int const& min_inclusive, unsigned int const& max_exclusive):
mt_(std::random_device()()),
dist_double_(NULL),
dist_u_int_(new std::uniform_int_distribution<unsigned int>(min_inclusive,max_exclusive))
{}
template<>
double Rand<double>::get(){ return (*dist_double_)(mt_); }
template<>
unsigned int Rand<unsigned int>::get(){ return (*dist_u_int_)(mt_); }
С практической точки зрения , решение шаблона более гибко с другими классами шаблонов, потому что я мог бы делать такие вещи, как:
template<typename Type>
classs C{
/*some code*/
private:
Rand<Type> r;
};
Мне нравится решение для шаблона. Но когда я проверяю время, необходимое для вызова метода Rand<double/unsigned int>::get()
, я понял, что он занимает более двух раз больше времени, чем звонок от RandDouble::get()
или RandUnisignedint::get()
.
Это способ сохранить гибкость метода шаблона с помощью метода вызова, который так же эффективен, как и у двух разных классов.
Как упомянуто ниже, проблема с указателем косвенности. Шаблоны C++ на самом деле создаются в режиме предварительного процессора и эффективно делают 2/3/4 классы для вас под капотом. Поэтому шаблоны не медленнее, чем ручные инструментальные классы (в зависимости от реализации) Мне очень интересно, я не вижу, где вы фактически используете mt_ внутри класса, который нуждается в более высокой точности, чем тот тип, который вы используете. Неправильно ли было бы заменить строку "std :: mt19937_64 mt_;" для "T mt__;" – chrispepper1989
@ chrispepper1989 Я использую mt_ в методе get ...это необходимо либо 'std :: uniform_real_distribution', либо 'std :: uniform_int_distribution ' –
PinkFloyd