3

これらの c++ のプリプロセッサとテンプレートの制限は私を殺しています。目標は、文字列リテラルを整数に変換することです。

template<const char* str>
inline int LiteralToInt(){
    return __COUNTER__;
}

using std::cout;

int main(){
    cout << LiteralToInt<"Hello">();
    cout << LiteralToInt<"No">();
    cout << LiteralToInt<"Hello">();
    return 0;
}

テンプレートが文字列リテラルを受け入れた場合、出力は 010 になります。この出力を取得し、コンパイル時に文字列リテラルを整数に変換する別の方法はありますか?

4

4 に答える 4

3

はい、C ++11はあなたのconstexprためにこれを行います:

 constexpr int LiteralToInt(const char * str) {
      return __COUNTER__; // or whatever.
 }
于 2012-08-03T03:31:45.427 に答える
1

このようなものはうまくいくでしょう

extern const char HELLO[] = "Hello";

その後

cout << LiteralToInt<HELLO>();

しかし、リテラル自体ではありません。これはおそらくあなたが望むものではありません。

すでに発見したように、文字列リテラル自体をテンプレート引数として使用することはできません。

于 2012-08-03T03:39:09.720 に答える
1

constexpr を使用してRichard J Ross III の答えについて少し考えてみると、検索するための正しいキーがわかりました...基本的に行っているのは、コンパイル時に文字列をハッシュすることです。ここに示すように、これは C++11 で実行できます (以前のバージョンでは実行できません) 。

基本的な考え方は、次のようなものを使用することです。

unsigned int constexpr const_hash(char const *input) { 
    // really simple hash function...
    return static_cast<unsigned int>(*input) 
         && static_cast<unsigned int>(*input) + hash(input+1); 
}

しかし、おそらくこれよりも堅牢なプロパティを持つハッシュ関数を使用したいでしょう...

ただし、C++11 を使用していない場合は、以前のステートメントが保持されます。

いいえ - コンパイル時に文字列リテラルを整数に変換する方法はありません。コードを処理する以外に、すべてのコンパイル単位で同じ文字列がすべて同じ値にマップされる (そして異なる文字列が異なる値にマップされる) ようにする方法はありません。何らかの方法で。

于 2012-08-03T05:17:37.173 に答える
0

残念ながら、私はあなたが望むことを正確に行う方法を知りません。

文字列に制限はありますか?文字数は?1〜8文字に制限できる場合は、次のようにすることができます。

template <char Ch1, char Ch2 = '\0', char Ch3 = '\0', char Ch4 = '\0', char Ch5 = '\0', char Ch6 = '\0', char Ch7 = '\0', char Ch8 = '\0'>
struct string_hash {
    static const uint64_t value = 
        (static_cast<uint64_t>(Ch1) << 56) | 
        (static_cast<uint64_t>(Ch2) << 48) | 
        (static_cast<uint64_t>(Ch3) << 40) | 
        (static_cast<uint64_t>(Ch4) << 32) | 
        (static_cast<uint64_t>(Ch5) << 24) | 
        (static_cast<uint64_t>(Ch6) << 16) | 
        (static_cast<uint64_t>(Ch7) << 8)  | 
        (Ch8);
};

これは基本的に、コンパイル時に8文字まで詰め込みますuint64_t。使用法は次のようになります。

const uint64_t x = string_hash<'T', 'e', 's', 't'>::value

これにより、1〜8文字の長さの各文字列に固有のコンパイル時の数値(switchおよびそのすべての機能で使用できます)が作成されます。残念ながら、唯一の大きな欠点は、文字列リテラルとして記述できないことです。リストとして記述する必要がありますchar

于 2012-08-03T04:51:06.507 に答える