自定义统一机器人无法编译

Custom UniformRandomBitGenerator fails to compile

本文关键字:编译 机器人 自定义      更新时间:2023-10-16

我正在尝试在返回uint_fast32_t中定义的随机数生成源周围创建一个包装器,以便一个基类可以将指针存储到任何RNG(std :: MT199937,std :: default_random等)。这是为了将随机数生成源存储为类成员,而无需将类作为模板类。我想到的解决方案:我定义了一个抽象的基类RNGsource,该基类实现了C 均匀型型型标准。然后,我定义了一个模板类RNGSourceWrap,该类别实现RNGSource,将一些C RNG源作为参数,并实现RNGSource函数以将呼叫转发到基础的C RNG存储。代码如下:

#ifndef RANDOM_H
#define RANDOM_H
#include <cstdint>

class RNGSource
{
    public: 
        virtual ~RNGSource() = default;
        typedef uint_fast32_t result_type;
        virtual result_type operator() () = 0;
        virtual result_type min() const = 0;
        virtual result_type max() const = 0;
};

template <class Generator>
class RNGSourceWrap : public RNGSource
{
    public:
        RNGSourceWrap(Generator* rng);
        virtual result_type operator() () override;
        virtual result_type min() const override;
        virtual result_type max() const override;
        Generator* rng() const;
    private:
        Generator* rngVal;
};
template <class Generator>
RNGSourceWrap<Generator>::RNGSourceWrap(Generator* rng)
    : rngVal(rng) { }
template <class Generator>
typename RNGSourceWrap<Generator>::result_type 
RNGSourceWrap<Generator>::operator() () { return rngVal->operator() (); }
template <class Generator>
typename RNGSourceWrap<Generator>::result_type 
RNGSourceWrap<Generator>::min() const { return rngVal->min(); }
template <class Generator>
typename RNGSourceWrap<Generator>::result_type 
RNGSourceWrap<Generator>::max() const { return rngVal->max(); }
template <class Generator>
Generator* RNGSourceWrap<Generator>::rng() const { return rngVal; }
#endif // RANDOM_H

我写了一个小主测试funtionalition:

#include "random.h"
#include <random>
#include <iostream>
int main()
{
    std::mt19937 rng;
    RNGSource* rngWrap = new RNGSourceWrap<std::mt19937>(&rng);
    std::uniform_int_distribution<int> distro(1, 6);
    int myInt = distro(*rngWrap);
    std::cout << myInt << std::endl;
    delete rngWrap;
    return 0;
}

使用C 14标准使用Linux G 和MingW编译时,该代码编译并运行,没有警告或错误。但是,使用MSVC编译(使用Visual Studio 2017社区)时会产生错误:

1>------ Build started: Project: RNGTestApp, Configuration: Debug Win32 ------
1>main.cpp
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.11.25503includexutility(3479): error C2352: 'RNGSource::max': illegal call of non-static member function
1>[PATH REMOVED]visual studio 2017projectsrngtestapprandom.h(14): note: see declaration of 'RNGSource::max'
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.11.25503includexutility(3476): note: while compiling class template member function 'std::_Rng_from_urng<unsigned int,_Engine>::_Rng_from_urng(_Urng &)'
1>        with
1>        [
1>            _Engine=RNGSource,
1>            _Urng=RNGSource
1>        ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.11.25503includerandom(2353): note: see reference to function template instantiation 'std::_Rng_from_urng<unsigned int,_Engine>::_Rng_from_urng(_Urng &)' being compiled
1>        with
1>        [
1>            _Engine=RNGSource,
1>            _Urng=RNGSource
1>        ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.11.25503includerandom(2353): note: see reference to class template instantiation 'std::_Rng_from_urng<unsigned int,_Engine>' being compiled
1>        with
1>        [
1>            _Engine=RNGSource
1>        ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.11.25503includerandom(2312): note: see reference to function template instantiation 'int std::uniform_int<_Ty>::_Eval<_Engine>(_Engine &,_Ty,_Ty) const' being compiled
1>        with
1>        [
1>            _Ty=int,
1>            _Engine=RNGSource
1>        ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.11.25503includerandom(2312): note: see reference to function template instantiation 'int std::uniform_int<_Ty>::_Eval<_Engine>(_Engine &,_Ty,_Ty) const' being compiled
1>        with
1>        [
1>            _Ty=int,
1>            _Engine=RNGSource
1>        ]
1>[PATH REMOVED]visual studio 2017projectsrngtestappmain.cpp(11): note: see reference to function template instantiation 'int std::uniform_int<_Ty>::operator ()<RNGSource>(_Engine &) const' being compiled
1>        with
1>        [
1>            _Ty=int,
1>            _Engine=RNGSource
1>        ]
1>[PATH REMOVED]visual studio 2017projectsrngtestappmain.cpp(11): note: see reference to function template instantiation 'int std::uniform_int<_Ty>::operator ()<RNGSource>(_Engine &) const' being compiled
1>        with
1>        [
1>            _Ty=int,
1>            _Engine=RNGSource
1>        ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.11.25503includexutility(3479): error C2352: 'RNGSource::min': illegal call of non-static member function
1>[PATH REMOVED]visual studio 2017projectsrngtestapprandom.h(13): note: see declaration of 'RNGSource::min'
1>Done building project "RNGTestApp.vcxproj" -- FAILED.

鉴于这确实使用Linux G 和MingW进行了编译,并且似乎有资格作为实现统一符号的标准,这是编译器错误吗?

在我看来,您理解了统一符号加工概念的措辞。result_typemaxmin都是定义的static,您的实现无法执行。虽然"静态"一词在配方中不使用,但请仔细观察表达方式。

在您的包装器中,您可以相应地包装:

template <class Generator>
typename RNGSourceWrap<Generator>::result_type 
RNGSourceWrap<Generator>::min() const { return Generator::min(); }

…并声明各自的方法静态。但是,如果有人致电RNGSource::min(),它将无效。

i存在一个问题,即从运行时可能从几个可能的预定义随机生成器中选择一个,并将其用于期望这种生成器的函数。很长一段时间后,我找到了

#include <iostream>
#include <random>
class RNGbase {
public:
    virtual ~RNGbase() = default;
    typedef uint32_t result_type;             //type has to be hardcoded in superclass?
    virtual result_type operator() () = 0;    //will be overridden in subclass
    inline static result_type (*min) ();      //function pointer will be set in subclass constructor
    inline static result_type (*max) ();      //function pointer will be set in subclass constructor
};
template <class R> class RNG : public RNGbase {
public:
    using result_type = typename R::result_type;
    R r;
    RNG() {
        RNGbase::min = R::min;
        RNGbase::max = R::max;
    }
    result_type operator() () override {
        return r();
    }
};

int main() {
    //dynamically create generator
    std::unique_ptr<RNGbase> rng = std::make_unique<RNG<std::random_device>>();
    //use generator for sampling
    std::vector<int> values { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    std::vector<int> samples(2);
    std::sample(values.cbegin(), values.cend(), samples.begin(), samples.size(), *rng);
    std::cout << "samples " << samples[0] << " " << samples[1] << std::endl;
    //use generator for number distributions
    std::uniform_int_distribution<int> distro(1, 6);
    std::cout << distro(*rng) << std::endl;
    return 0;
}