【问题标题】:Custom UniformRandomBitGenerator fails to compile自定义 UniformRandomBitGenerator 无法编译
【发布时间】:2017-09-08 23:27:45
【问题描述】:

我正在尝试围绕 C++ 标头中定义的返回 uint_fast32_t 的随机数生成源创建一个包装器,以便一个基类可以存储指向任何 RNG(std::mt19937、std::default_random 等)的指针。这是为了将随机数生成源存储为类成员,而不必使该类成为模板类。我想出的解决方案:我定义了一个抽象基类 RNGSource,它实现了 C++ UniformRandomBitGenerator 标准。然后,我定义了一个实现 RNGSource 的模板类 RNGSourceWrap,将一些 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

我写了一个小 main 来测试功能性:

#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;
}

当使用 Linux g++ 和 MinGW 使用 c++ 14 标准编译时,此代码编译和运行时不会出现警告或错误。但是,使用 MSVC(使用 Visual Studio 2017 社区)编译时会产生错误:

1>------ Build started: Project: RNGTestApp, Configuration: Debug Win32 ------
1>main.cpp
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.11.25503\include\xutility(3479): error C2352: 'RNGSource::max': illegal call of non-static member function
1>[PATH REMOVED]\visual studio 2017\projects\rngtestapp\random.h(14): note: see declaration of 'RNGSource::max'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.11.25503\include\xutility(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 studio\2017\community\vc\tools\msvc\14.11.25503\include\random(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 studio\2017\community\vc\tools\msvc\14.11.25503\include\random(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 studio\2017\community\vc\tools\msvc\14.11.25503\include\random(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 studio\2017\community\vc\tools\msvc\14.11.25503\include\random(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 2017\projects\rngtestapp\main.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 2017\projects\rngtestapp\main.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 studio\2017\community\vc\tools\msvc\14.11.25503\include\xutility(3479): error C2352: 'RNGSource::min': illegal call of non-static member function
1>[PATH REMOVED]\visual studio 2017\projects\rngtestapp\random.h(13): note: see declaration of 'RNGSource::min'
1>Done building project "RNGTestApp.vcxproj" -- FAILED.

鉴于这确实使用 Linux g++ 和 MinGW 进行编译,并且似乎有资格实现 UniformRandomBitGenerator 标准,这是编译器错误吗?

【问题讨论】:

标签: c++ c++14


【解决方案1】:

在我看来,您对 UniformRandomBitGenerator 概念的措辞理解错误。 result_typemaxmin 都将被定义为 static,而您的实现未能做到这一点。虽然公式中没有使用“静态”一词,但请仔细查看表达式的编写方式。

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

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

... 并将相应的方法声明为静态。但是,如果有人打电话给RNGSource::min(),那将是无效的。

【讨论】:

  • 这是有道理的(不幸的是打破了我在做什么的概念),但是出于好奇,尽管它们是静态的,为什么代码至少在 2 个 C++ 上编译编译器什么时候不是?
  • 你不是在 MinGW 上使用 GCC 吗?那么它将是一个编译器。这只是标准库的一个随机细节。如果你手头有一个随机数生成器Rng 的对象rng,你可以写rng-&gt;max()Rng::max()。似乎 GCC 开发人员选择了第一个选项,而 MSVC 选择了第二个。如果max() 不是静态的,则只有第二个失败。
  • 这是有道理的。不幸的是,将各自的方法声明为 static 对我没有多大好处,因为正是您提到的原因——如果有人调用 RNGSource::min() 它会失败(如果我尝试过类似 std::uniform_int_distribution 会这样做在我的 main() 示例中将其传递给 RNGSource 的引用)。即便如此,它也完美地回答了这个问题。谢谢!
  • 如果您认为答案有帮助,请采纳,见meta.stackexchange.com/questions/5234/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-06
  • 2017-03-20
  • 2017-07-29
相关资源
最近更新 更多