Skip to content

Instantly share code, notes, and snippets.

@yumetodo
Last active October 27, 2022 10:19
Show Gist options
  • Save yumetodo/68bd4796e128babb506766c03f116641 to your computer and use it in GitHub Desktop.
Save yumetodo/68bd4796e128babb506766c03f116641 to your computer and use it in GitHub Desktop.
random_device warkaround for mingw gcc
*.exe
*.out
.vscode/
#include "random_device.hpp"
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
using seed_v_t = std::vector<cpprefjp::random_device::result_type>;
seed_v_t create_seed_v()
{
cpprefjp::random_device rnd;
seed_v_t sed_v(9);
std::generate(sed_v.begin(), sed_v.end(), std::ref(rnd));
return sed_v;
}
int main()
{
const auto sed_v = create_seed_v();
std::seed_seq seq(sed_v.begin(), sed_v.end());
std::mt19937 engine(seq);
std::uniform_int_distribution<int> dist(1, 32);
for(int i = 0; i < 10; ++i) std::cout << dist(engine) << std::endl;
}
#include <random>
#if defined(__MINGW32__) && defined(__GNUC__) && !defined(__clang__)
#include <system_error>
#include <limits>
#include <string>
#include <Windows.h>
#include <wincrypt.h>
namespace workaround_mingw_gcc {
class random_device {
private:
class crypt_context {
private:
HCRYPTPROV prov_;
public:
crypt_context(DWORD prov_type, LPCTSTR container = nullptr, LPCTSTR provider = nullptr, DWORD flags = 0)
{
using std::system_category;
using std::system_error;
const auto er = ::CryptAcquireContext(&this->prov_, container, provider, prov_type, flags);
if(!er) {
throw system_error(
std::error_code(::GetLastError(), system_category()),
"CryptAcquireContext:(" + std::to_string(er) + ')'
);
}
}
crypt_context(const crypt_context&) = delete;
void operator=(const crypt_context&) = delete;
~crypt_context() noexcept
{
::CryptReleaseContext(this->prov_, 0);
}
//HCRYPTPROV& get() noexcept { return this->prov_; }
const HCRYPTPROV& get() const noexcept { return this->prov_; }
};
crypt_context prov_;
public:
using result_type = unsigned int;
explicit random_device(const std::string& /*token*/ = "workaround_mingw_gcc ")
: prov_(PROV_RSA_FULL)
{}
random_device(const random_device&) = delete;
void operator=(const random_device&) = delete;
//~random_device() = default;
double entropy() const noexcept { return 0.0; }
result_type operator()()
{
using std::system_category;
using std::system_error;
result_type re;
const auto er = ::CryptGenRandom(this->prov_.get(), sizeof(re), reinterpret_cast<BYTE*>(&re));
if(!er) {
throw system_error(
std::error_code(::GetLastError(), system_category()),
"CryptGenRandom:(" + std::to_string(er) + ')'
);
}
return re;
}
static constexpr result_type min() { return std::numeric_limits<result_type>::min(); }
static constexpr result_type max() { return std::numeric_limits<result_type>::max(); }
};
}
namespace cpprefjp {
using workaround_mingw_gcc::random_device;
}
#else //defined(__MINGW32__) && defined(__GNUC__) && !defined(__clang__)
namespace cpprefjp {
using std::random_device;
}
#endif //defined(__MINGW32__) && defined(__GNUC__) && !defined(__clang__)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment