rti*_*277 3 random constexpr c++11
我的应用包含大量ID.我想最终让其他人可以查看代码,但是不要让运行时反向工程师轻松查找容易知道的ID.此外,在开发期间,在日志文件中具有常量ID以便于调试是有帮助的.但是在运行时我想通过在Release编译期间生成这些ID来使它们随机.使用<random>
lib的建议代码可以在GetRandomId1()
下面看到.constexpr
像在switch语句中那样在代码中使用它们.但是,我constexpr
在提议的功能中使用时遇到了问题,因为<random>
它不constexpr
兼容.还有另一种在编译时生成随机数的方法吗?或者是在编译时生成随机数,以便在运行时用作常量来考虑constexpr
?
#include <iostream>
#include <random>
// this is the code I would like to use to generate a random number at compile time
/*constexpr */int GetRandomId1()
{
std::random_device rd; // non-deterministic seed
std::mt19937 gen( rd() ); // with constexpr uncommented:
// error C3250: 'rd': declaration is not allowed in 'constexpr' function body
// error C3249: illegal statement or sub-expression for 'constexpr' function
// error C3250: 'gen': declaration is not allowed in 'constexpr' function body
std::uniform_int_distribution<> distri( 1000, 9999 ); // with constexpr uncommented:
// error C3250: 'distri': declaration is not allowed in 'constexpr' function bod
// error C3249: illegal statement or sub-expression for 'constexpr' function
// error C2134: 'std::uniform_int<_Ty>::operator ()': call does not result in a constant expression
return distri( gen );
}
// this code is what works so far
constexpr int GetRandomId2()
{
return 22; // how to make somewhat random?
}
constexpr int AAA = 10;
//constexpr int AAA = GetRandonId1(); // error: is not constexpr function
constexpr int BBB = GetRandomId2(); // ok
void Func1( long ab )
{
switch( ab )
{
case AAA:
std::cout << AAA << std::endl;
break;
case BBB:
std::cout << BBB << std::endl;
break;
}
}
int main()
{
Func1( 22 ); // ok: prints 22
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我正在寻找一个像我提出的那样直接,可维护的解决方案,而不像我在如何在编译时生成密集的唯一类型ID那样大量使用模板?.同样在这篇帖子中@jmihalicza指向C++模板元程序研究论文的随机数生成器.本文描述了使用模板元编程生成编译时随机数,这是一个复杂的尝试,它完成了IMO constexpr
(我敢说,或者应该已经?)设计的任务.
由于应用程序架构原因,我不必担心ID冲突,因此这不是一个问题.应用程序代码将确保不会返回重复项.
我给了一个constexpr
随机数发生器这里前一段时间,为相关的目的constexpr
字符串加密,以帮助对你所关心的同一对手.
我认为它具有与mt19937相当的加密安全性,mt19937是一个(非常复杂的)线性反馈生成器,并且无论如何都不是真正的加密安全.
此代码中的想法是使用__TIME__
和__LINE__
作为生成器的种子.
typedef uint32_t u32;
typedef uint64_t u64;
typedef unsigned char uchar;
template<u32 S, u32 A = 16807UL, u32 C = 0UL, u32 M = (1UL<<31)-1>
struct LinearGenerator {
static const u32 state = ((u64)S * A + C) % M;
static const u32 value = state;
typedef LinearGenerator<state> next;
struct Split { // Leapfrog
typedef LinearGenerator< state, A*A, 0, M> Gen1;
typedef LinearGenerator<next::state, A*A, 0, M> Gen2;
};
};
// Metafunction to get a particular index from generator
template<u32 S, std::size_t index>
struct Generate {
static const uchar value = Generate<LinearGenerator<S>::state, index - 1>::value;
};
template<u32 S>
struct Generate<S, 0> {
static const uchar value = static_cast<uchar> (LinearGenerator<S>::value);
};
// Seed
#define RNG_SEED ((__TIME__[7] - '0') * 1 + (__TIME__[6] - '0') * 10 + \
(__TIME__[4] - '0') * 60 + (__TIME__[3] - '0') * 600 + \
(__TIME__[1] - '0') * 3600 + (__TIME__[0] - '0') * 36000) + \
(__LINE__ * 100000)
Run Code Online (Sandbox Code Playgroud)
我并没有尝试使用constexpr
而不是使用模板来重写它,但是我认为在C++ 11标准中使用constexpr
函数来处理所有复杂的事情并不比模板好得多.它只是在C++ 14标准中真正变得很好,当你实际上可以有局部变量等等.
无论如何它仍然不应该那么难,这个发电机实现并没有那么糟糕.
你绝对需要放弃std::random_device
在编译时与之交谈的梦想.IIRC,在libc++
实施中,基本上是一个薄的包装std::fopen("/dev/urandom")
.我不知道任何允许在constexpr
计算中进行文件系统操作的C++标准或提议.:)
归档时间: |
|
查看次数: |
698 次 |
最近记录: |