2017-09-08 83 views
1

我試圖創建一個圍繞在C++頭定義的隨機數生成源返回uint_fast32_t的包裝,使得一個基類可以存儲指向任何RNG(標準:: mt19937,性病:: default_random等)。這是爲了將隨機數生成源存儲爲類成員,而不必將該類作爲模板類。我提出的解決方案是:我定義了一個抽象基類RNGSource,它實現了C++ UniformRandomBitGenerator標準。然後,我所定義的模板類RNGSourceWrap實現RNGSource,需要一些C++ RNG源作爲參數,並且實現RNGSource功能轉發到底層C++ RNG存儲呼叫。的代碼如下:定製UniformRandomBitGenerator編譯失敗

#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 

我寫了一個小主測試funtionality:

#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克++編譯並使用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標準,這是一個編譯器錯誤?

+0

https://stackoverflow.com/questions/30571141/pack-type-erase-a-random-number-generator/32555276#32555276 –

回答

0

在我看來,你理解UniformRandomBitGenerator概念錯誤的措辭。 result_typemaxmin都被定義static,你的執行沒有這樣做。雖然在表述中沒有使用「靜態」一詞,但仔細看看錶達式是如何寫入的。

在你封裝器,您可以相應地包裝:

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

...並宣佈各自的方法是靜態的。但是,如果有人打電話RNGSource::min()這將是無效的。

+0

這是有道理的(不幸的是打破了我在做什麼的概念),然而,出於好奇,儘管它們是靜態的,但爲什麼代碼至少要在2個C++編譯器上編譯? –

+0

您是不是在MinGW上使用GCC?那麼它將是一個編譯器。這只是標準庫的一個隨機細節。如果你手中有一個隨機數發生器'Rng'的對象'rng',你可以寫'rng-> max()'或'Rng :: max()'。看來GCC開發者選擇了第一個選項,而MSVC則選擇了第二個選項。如果max()不是靜態的,那麼只有第二個失敗。 – ypnos

+0

這是有道理的。不幸的是,宣佈因爲正是你所提到的原因,靜不幫我很多好各自的方法 - 如果有人致電RNGSource :: MIN(),它會失敗(這如果我想是這樣的std :: uniform_int_distribution會做把它作爲我的main()例子中的一個RNGSource的引用)。即便如此,它完美地回答了這個問題。謝謝! –