2016-07-26 9 views
2

マイアプリには多数のIDが含まれています。私は最終的に他の人がコードを見ることができるようにしたいが、実行時のリバースエンジニアが容易に知られているIDを探すのは簡単ではない。また、開発中に、簡単なデバッグのためにログファイルに一定のIDを持たせると便利です。しかし、実行時には、これらのIDをReleaseコンパイル中に生成することでランダムにしたいと考えています。 <random>のlibを使用する推奨されるコードは、下記のGetRandomId1()に記載されています。 constexprはswitch文のようにコード内で使用できます。しかし、<random>constexprに対応していないため、私の提案する機能でconstexprを使用することに問題があります。コンパイル時に乱数を生成する別の方法はありますか?あるいは、実行時に定数として使用されるコンパイル時に乱数を生成して、constexprという概念に反して考えていますか?コンパイル時に生成されたランダムIDでマジックID番号を置換する

#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; 
} 

私はまっすぐ進む、私が提案したようなとHow can I generate dense unique type IDs at compile time?で提案されているテンプレートの多用とは異なり、保守ソリューションを探しています。またこの投稿で@jmihaliczaはRandom number generator for C++ template metaprograms研究論文を指しています。この論文では、IMO constexprが(私が言いましたか、あるいはしていたはずの)タスクを実現する複雑な試みである、テンプレートメタプログラミングを使用したコンパイル時の乱数生成について説明します。

アーキテクチャ上の理由から、私はIDの衝突について心配する必要がないので、心配はありません。アプリコードは、重複が返されないようにします。

+6

ファイルに乱数を生成するカスタムビルド前のステップをいつでも追加することができます。 '#include'dになります – sp2danny

答えて

4

私はconstexpr乱数発生器hereをしばらく前に、constexprの関連する目的のために、あなたが懸念しているのと同じ敵を助けるために文字列の暗号化を行った。

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) 

複雑で、すべてのもののためにconstexprの機能を使用すると、テンプレートよりも大幅に進歩していない11の標準を私の代わりにテンプレートのconstexprを使用して、これを書き換えしようとしませんでしたが、TBH、私はC++で考えます。実際にはローカル変数などを持つことができるときには、C++ 14標準ではうまくいきます。

これはまだ難しくありません。この発電機の実装はそれほど悪くはありません。

あなたは間違いなくコンパイル時にstd::random_deviceと話す夢を放棄する必要があります。 IIRCはlibc++の実装では、基本的にstd::fopen("/dev/urandom")を超える薄いラッパーです。私はconstexpr計算の中でファイルシステム操作を可能にするC++の標準や提案を知らない。 :)

+0

「暗号的に安全」とはどういう意味ですか?コンパイル時にそれがなぜ必要なのですか?それは 'constexpr'の背後にある論理的根拠ですか?プログラマが特定の 'constexpr'関数のスコープ内のコードを制御しているので私の考え方に従えば、残りのプログラムのために何を' const'として扱うべきかを決定するのは彼自身でなければなりません。この決定は、コンパイル時に、メンバー変数がパブリック、プライベート、または保護されているかどうかを決定することに過ぎません。 – rtischer8277

+0

問題は、 'constexpr'リテラル型を生成するためにコンパイラがどのようなコードを実行できるのでしょうか?あなたのソリューションのようなメタプログラミングのようにヘッダーのみでなければなりませんか? 'constexpr'のポイントがありません。それは外部のファイルコードに委ねられるべきですか?ポイントも逃してしまう。 – rtischer8277

+0

'constexpr'が何であるかについていくつかの誤解があると思います。 'constexpr'は' const'と同じではなく、 'public、private'などとはまったく関係ありません。コンパイラの最適化を有効にすることとは何の関係もありません。コンパイラがコンパイル時に式を計算できれば、 as-ifルールの下でそれを最適化することはすでに自由です。 'constexpr'の最も重要な利点は、リテラル型をテンプレートパラメータとして使用できることです。 –

関連する問題