2015-06-01 26 views
11

Thư viện std C++ 11 có một số trình tạo số ngẫu nhiên (RNG), mỗi lần thực hiện khái niệm UniformRandomNumberGenerator. Sau đó, chúng có thể được sử dụng làm đối số cho các bản phân phối ngẫu nhiên, xem thêm this documentation để biết tổng quan.gói (loại xóa) một trình tạo số ngẫu nhiên

Ưu điểm của thiết kế này là sự lựa chọn của động cơ RNG cơ bản là de-coupled từ ứng dụng của nó. Tuy nhiên, thiết kế cũng yêu cầu định nghĩa (không chỉ đơn thuần là các khai báo) của tất cả các cuộc gọi tới RNG để có sẵn (nếu kiểu RNG vẫn không được chỉ định làm tham số mẫu). Như vậy, trong

struct complicated_random_distribution 
{ 
    /* 
    some data and auxiliary methods here 
    */ 
    // complicated; may call RNG::operator() many times 
    template<typename RNG> 
    some_type operator()(RNG&gen) const; 
}; 

thành viên operator() không thể được thực hiện thẳng thắn trong một đơn vị biên soạn riêng biệt (CU), nhưng phải có sẵn trong file header cùng (hoặc một #include d từ nó).

Để thực hiện riêng biệt, một cách lý tưởng sẽ muốn có cách nào đó để đóng gói RNG theo cách giống như std::function<> gói bất kỳ đối tượng có thể gọi nào. (Chỉ cần sử dụng std::function và cung cấp các giá trị cho RNG::min()RNG::max() làm đối số cho hàm được xác định trong CU riêng biệt là hạn chế và sẽ không cho phép sử dụng, ví dụ: std::uniform_real_distribution<> bên trong).

Làm cách nào để thực hiện điều này? Các triển khai cho tính năng này có sẵn không? Thư viện std sẽ cung cấp thư viện này trong tương lai? Hay tôi sau một cá trích đỏ?


Sửa máy phát điện số ngẫu nhiên được yêu cầu phải có static thành viên min()max(), làm kiểu tẩy xoá cứng hoặc không thể (libstdc GNU của ++ không làm cho giả thiết này và một loại tẩy xoá với các thành viên không tĩnh min()max() hoạt động, nhưng không phải với libC++ của LLVM, sử dụng tiêu chuẩn yêu cầu static thành viên). Có cách nào để giải quyết vấn đề này không? Nếu không, điều này có nghĩa là chuẩn C++ có giao diện bị hỏng cho các trình tạo số ngẫu nhiên không?

+0

Bạn có thể dễ dàng thực hiện điều đó ra khỏi dòng, định nghĩa chỉ cần có trong file header. Điều đó thực sự rất tệ? –

+1

Cụm từ bạn đang tìm kiếm là "loại xóa", không phải "gói". Ngoài ra, bạn sẽ xử lý 'min()' và 'max()' như thế nào? Tất cả URNG có cùng phạm vi không? Tôi giả sử không? – Barry

+0

@Walter Bạn chắc chắn có thể: http://coliru.stacked-crooked.com/a/47941423fc589739 Vâng, có lẽ chúng ta đang nói về những thứ khác nhau. –

Trả lời

2

Chỉnh sửa lại RNG với một independent_bits_engine, và gõ xóa RNG thích nghi. Bạn có kiến ​​thức đầy đủ về những gì min()max() của independent_bits_engine.

Dưới đây là một phác thảo:

struct RNG_wrapper { 
    using result_type = std::uint32_t; 
    static constexpr result_type min() { return 0; } 
    static constexpr result_type max() { return 0xFFFFFFFF; } 

    template<class RNG> 
    using my_engine_type = std::independent_bits_engine<RNG, 32, result_type>; 

    template<class RNG, 
      class = std::enable_if_t<!std::is_same<std::decay_t<RNG>, RNG_wrapper>{}>> 
    RNG_wrapper(RNG&& r) 
     : rng(my_engine_type<std::decay_t<RNG>>(std::forward<RNG>(r))) {} 

    result_type operator()() { return rng(); } 
    std::function<result_type()> rng; 
}; 
+0

Bây giờ tôi hiểu ý tưởng: bằng cách sử dụng một 'độc lập_bits_engine' bạn có thể tạo ra' min' và 'max' tĩnh, bởi vì chúng chỉ phụ thuộc vào số bit tĩnh .. thông minh! – Walter

1

Điều này hoạt động trong clang và gcc (với libstdC++), nhưng điều này không đúng là UniformRandomNumberGenerator, vì lý do ghi nhận rằng minmax không tĩnh.

#include <cassert> 
#include <random> 
#include <functional> 
#include <iostream> 

template<typename T> 
class AnyUniformRandomNumberGenerator 
{ 
    T mMin; 
    T mMax; 
    std::function<T()> mValue; 
public: 

    using result_type = T; 

    template<typename UniformRandomNumberGenerator> 
    AnyUniformRandomNumberGenerator(UniformRandomNumberGenerator uniformRandomNumberGenerator) : 
    mMin(UniformRandomNumberGenerator::min()), 
    mMax(UniformRandomNumberGenerator::max()), 
    mValue([=]() mutable { return uniformRandomNumberGenerator(); }) 
    {} 

    T operator()() 
    { 
     return mValue(); 
    } 

    T min() 
    { 
     return mMin; 
    } 

    T max() 
    { 
     return mMax; 
    } 
}; 

int main() 
{ 
    std::default_random_engine rng; 
    AnyUniformRandomNumberGenerator<decltype(rng())> any{rng}; 

    assert(any() <= any.max()); 
    assert(any() >= any.min()); 

    std::uniform_int_distribution<> dist{1, 6}; 

    std::cout << dist(any); 
} 

GCC: http://rextester.com/ANAP79935

kêu vang http://rextester.com/YCIIR21607

+0

@Walter Nó là một điều libstdC++ tôi nghĩ. Nếu bạn thay đổi thành libstdC++ trong táo clang, tôi đoán nó sẽ hoạt động. – tahsmith

+1

@Walter Tôi nghĩ rằng rextester sử dụng libstdC++ với Clang. –

+0

Đây thực chất là những gì tôi đã thử ban đầu, nhưng những gì không biên dịch với 'clang ++ -stdlib = libC++ -std = C++ 11'. Việc bạn sử dụng 'libstdC++' làm cho nó hoạt động, nhưng đó không phải là sự tuân thủ tiêu chuẩn. – Walter

Các vấn đề liên quan