2011-08-08 13 views
4

をカウントするために、私は文字のリストに文字列を変換するマクロを持っている:マクロ(文字)の引数

例えば
#define TO_STRING(x) #x 
#define CHAR_LIST_7(x) TO_STRING(x)[0] \ 
         , TO_STRING(x)[1] \ 
         , TO_STRING(x)[2] \ 
         , TO_STRING(x)[3] \ 
         , TO_STRING(x)[4] \ 
         , TO_STRING(x)[5] \ 
         , TO_STRING(x)[6] 

使用法: "CHAR_LIST_7(chicken)"は "c"、 "h"、 "i"、 "c"、 "k"、 "e"、 "n" "を与えます。 :http://hpaste.org/47313/exand

しかし、私はこれを任意の文字数で一般化したいと思います(手作業で文字数をカウントする必要はありません)。だから私は単純に行くことができます:CHAR_LIST(任意のテキスト)。任意のアイデアやソリューションですか?

+0

好奇心ではない:何のために必要なのですか? –

+2

明らかに、C++のメタプログラミング能力の濫用の限界を過ぎています(実際にそこに到達するのに時間はかかりません、btw)。あなたが直面している問題は、実際のものではなく、C++のメタプログラミング限界の小さなケージにあなたの心を込めた意図的な決定によって作られた幽霊であることを認識していますか?あなたが楽しいためにこれを行うなら、brainf ** ckを代わりに使ってC++を生成することに全力で取り組んでみませんか? – 6502

+0

@ 6502、私はこの質問が答え(私によって与えられた)[SOの他の場所](http://stackoverflow.com/a/6191216/146041)から来たと思います。あなたのコメントを愛していますが、私はまさに幽霊と戦うために来ています。私はSOを訪問したときに私のプラグマティズムを忘れています:-) –

答えて

3

前処理中にトークンを分割することはできません。それらは組み合わせることができます(##を使用)。

識別子を文字列リテラルに変換することは、文字列リテラルで文字列リテラルを分割したり、文字列リテラルで操作(たとえば、長さの計算)を実行できないため役に立ちません。

前処理中に、コンパイラはトークンが文字列リテラルであり、どのようなリテラルであるかを知っていますが、少なくとも完全な型と長さはマクロにはアクセスできない方法では認識しません。

+0

それは本当に文字列ではありません。それは識別子です。 (編集:私は解決策を見つけることに役立つだろうと考えていたが、何も思い付きません。おそらくこれは不可能です...) –

+0

ああ、私は#xの最初の行に気を散らせましたOPのコード。それは本当に問題ではありません。答えは同じです。 –

+1

私はC++ではない0x - 'constexpr'として宣言された関数の出力をテンプレートの引数として与えることはできますか? –

1

一般的な形態では分けを求める方法はできません。私はそれがタイピングのもう少しになることを知っている

Literal<'c','h','i','c','k','e','n'>::print(); 

:最良の方法は、それはtemplateにだとして引数を提供することです。それを克服するために、chickenのような文字列リテラルを引数に取る単純なプログラムを書くことができ、'c''h''i'、...などに出力します。以下のようなもの:

int main(int argc, char **argv) 
{ 
    if(argc != 2) 
    return 0; 
    const char *s = argv[1]; 
    int length = strlen(s)-1; 
    for(int i = 0; i < length; i++) 
    cout<<s[i]<<","; 
    cout<<s[length]<<endl; 
} 

はしかし、あなたのtemplate引数に文字-テッドの分割による冗長性のための解決策はありません。

+0

私はあなたが一度に4文字を渡すためにマルチバイト文字を悪用することができると思う...かなりあまりにも:/ –

1

いいえ、Jamesはすでに述べたように、プリプロセッサでトークンを分割したり、文字列の長さを知ることはできません。

しかし、あなたのユースケースでは、これはどの場合でも必要ないと思います。引数を#xでストリング化することによって得られる文字列は、一定のサイズの文字列です(例:chicken)。char[8]のような"chicken"になります。そのような文字列の長さはコンパイル時の定数であり、あなたは、単にsizeofでそれを検出することができます:Cでそのような事の

#define TOKLEN(TOK) (sizeof(#TOK)-1) 

使用法「を単に」

#define SCARY(TOK) for (size_t i = 0; i < TOKLEN(TOK); ++i) printf("%c:", #TOK[i]) 

を見てしまうTOKLEN(TOK)であるためコンパイル時定数コンパイラが適切な場合にこれを展開できます。

C++

template < size_t n > 
class constLenString { 
    size_t const len = n; 
    char const* str; 
    constLenString(char* s) : str(s) { } 
}; 

#define defConstLenString(TOK, NAME) constLenString< TOKLEN(TOK) > NAME(#TOK) 

についてご利用の場合(未テスト、私のC++が錆びている)

となりまし

defConstLenString(chicken, chick); 

chick.nとすることができる一定であることを使用するにはforループのバインドやコンパイラは、すべてを完全に最適化できるはずです。

+0

私はOPがテンプレートパラメータとして文字列を渡そうとしていると思う。 –

関連する問題