用编译时生成的随机ID替换魔术ID号

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冲突,因此这不是一个问题.应用程序代码将确保不会返回重复项.

Chr*_*eck 5

我给了一个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++标准或提议.:)