我正在做一个上学的项目(因为命名空间名称可能暗示,它是 2D 游戏)并且我制作了一个名为 RangeInt(Range) 的自定义类,它只包装了两个相同类型的变量,并制作了另一个名为 Randomizer 的类,它包装了 C++ 11 标准随机数生成并使用 RangeInt 类指定我要生成数字的范围。
无论如何,这里是代码:
namespace game{
template<class _Type>
//very simple class representing virtual Range
//of type _Type(template argument) and storing
//upper and lower bound
class Range{
public:
typedef _Type TemplateParam;
//value sto use of type _Type
_Type first, second;
//copy constructor:
Range(const Range& rng)
{
first = rng.first;
second = rng.second;
}
//move construct:
Range(Range&& rng)
{
std::swap(*this, rng);
}
Range& operator=(const Range& range)
{
first = range.first;
second = range.second;
return *this;
}
Range& operator=(Range&& range)
{
std::swap(first, range.first);
std::swap(second, range.second);
return *this;
}
//constructor
Range(_Type one, _Type two) : first(one), second(two) {}
//returns two - one
inline _Type getDifference() { return two - one; }
};
typedef Range<uint> RangeInt;
};
和随机器:
namespace game{
template <class _RNG = xorshift>
class Randomizer_RNG{
typedef _RNG random_generator;
RangeInt rng;
random_generator mt;
std::uniform_int_distribution<> dist;
//reinitialize the dist variable so it actually knows the new range
void _changeDist()
{
dist = std::uniform_int_distribution<>(rng.first, rng.second);
}
public:
//default constructor, set rng to maximum range and initialize
//the xorshift with seed being current time and specify the
//range for uniform_int_distribution
Randomizer_RNG()
{
rng = game::RangeInt(0, std::numeric_limits<game::uint>::max());
dist = std::uniform_int_distribution<>(range.first, range.second);
mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
}
//do the same as constructor above but with specified range
explicit Randomizer_RNG(RangeInt range) : rng(range)
{
dist = std::uniform_int_distribution<>(rng.first, rng.second);
mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
}
//copy constructor
Randomizer_RNG(const Randomizer_RNG& lhs)
{
dist = lhs.dist;
mt = lhs.mt;
rng = lhs.rng;
}
//move constructor
Randomizer_RNG(Randomizer_RNG&& lhs)
{
std::swap(*this, lhs);
}
//reseed with current time
inline void seed()
{
mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
}
//reseed with specified value
inline void seed(unsigned long long newSeed)
{
mt.seed(newSeed);
}
//default operator()
uint32 operator()()
{
return dist(mt);
}
//return value generated in range of
//<fitWithin.first, fitWithin.second>
uint32 operator()(RangeInt&& fitWithin)
{
decltype(dist) l_dist(fitWithin.first, fitWithin.second);
return l_dist(mt);
}
//the same as above, but with rvalue reference
uint32 operator()(RangeInt& fitWithin)
{
decltype(dist) l_dist(fitWithin.first, fitWithin.second);
return l_dist(mt);
}
//change range with reference
void changeRange(const RangeInt& rng)
{
this->rng = rng;
_changeDist();
}
//the same as above but with rvalue reference
void changeRange(RangeInt&& rng)
{
std::swap(this->rng, rng);
_changeDist();
}
//set the upper bound of the range and update rng
void setUpperBound(RangeInt::TemplateParam upBound)
{
rng.second = upBound;
_changeDist();
}
//set the lower bound of the range and update rng
void setLowerBound(RangeInt::TemplateParam lowBound)
{
rng.first = lowBound;
_changeDist();
}
//copy assignment
Randomizer_RNG& operator=(const Randomizer_RNG& lhs)
{
_RETURN_IF_THIS(lhs, *this); //if (*this == lhs) return *this;
rng = lhs.rng;
changeRange(rng);
return *this;
}
//move assignment
Randomizer_RNG& operator=(Randomizer_RNG&& lhs)
{
dist = std::move(lhs.dist);
rng = std::move(lhs.rng);
mt = std::move(lhs.mt);
return *this;
}
};
typedef Randomizer_RNG<> Randomizer;
typedef Randomizer_RNG<std::mt19937> Randomizer_Twist;
};
但是当我这样做时
#include "randomizer.h"
int main()
{
game::RangeInt rngI (14, 546);
game::Randomizer rng = game::Randomizer(game::RangeInt(0, 100));
auto func = std::bind(rng, rngI);
std::cout << func();
std::cin.get();
}
它弹出编译器错误:
error C2512: 'game::Range<_Type>' : no appropriate default constructor available
with
[
_Type=game::uint
]
如果我尝试这样做:
#include "randomizer.h"
int main()
{
game::RangeInt rngI (14, 546);
game::Randomizer rng = game::Randomizer(game::RangeInt(0, 100));
auto func = std::bind(&rng, rngI);
std::cout << func();
std::cin.get();
}
它说:错误C2679:二进制'<<':未找到采用'std::_Do_call_ret<_Forced,_Ret,_Funx,_Btuple,_Ftuple>::type'类型的右手操作数的运算符(或者没有可接受的转换)
所以我想知道我是否做错了什么,或者为什么 std::bind 需要我为游戏::Range 提供默认构造函数。
如果我的问题不清楚或代码不清楚,请告诉我,我会尽力而为。
PS:我使用 Visual Studio 2012,所以没有实现可变参数模板(例如 std::bind 有 378 个重载)