std :: bind需要默认构造函数

时间:2013-10-16 19:25:31

标签: c++ visual-studio-2012 c++11

我正在研究一个到学校的项目(因为命名空间名称可能提示,它是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:二进制&#39;&lt;&lt;&# :没有找到哪个运算符采用类型&#39; std :: _ Do_call_ret&lt; _Forced,_Ret,_Funx,_Btuple,_Ftuple&gt; :: type&#39;的右手操作数(或者没有可接受的转换)

所以我想知道我做错了什么或为什么std :: bind想要来自我的默认构造函数game :: Range。

如果我的问题不明确或代码不清楚,请告诉我,我会尽力而为。

PS:我使用Visual Studio 2012,因此没有实现Variadic模板(例如std :: bind有378个重叠)

1 个答案:

答案 0 :(得分:2)

成功

Randomizer_RNG(const Randomizer_RNG& lhs)
   : dist(lhs.dist), mt(lhs.mt), rng(lhs.rng)
{}

或者完全删除这个构造函数:编译器生成的构造函数就足够了。

如上所述,构造函数首先尝试默认构造rng,然后分配给它。但是,正如编译器告诉您的那样,Range不提供默认构造函数。