質問

私は、連結によって形成された多くの一定の文字列があるプロジェクトに取り組んでいます(数字など)。

たとえば、私はaを持っています LOCATION フォーマットのマクロ __FILE____LINE__ メッセージやエラーを印刷するときに、コードのどこにいるかを知るために使用できる文字列に:

#define _STR(x)    # x
#define STR(x)     _STR(x)
#define LOCATION __FILE__ "(" STR(__LINE__) ")"

したがって、これは「file.cpp(42)」のような場所を形成します。問題は、結果をワイドストリングに変換しようとするときです。

#define _WIDEN(x)  L ## x
#define WIDEN(x)   _WIDEN(x)
#define WLOCATION  WIDEN(LOCATION)

これはGCCで正常に機能し、l "file.cpp(42)"がコードに挿入されます。ただし、MSVC ++(Visual C ++ 2008 Expressを使用)でこれを試すと、エラーが発生します。

error: Concatenating wide "file.cpp" with narrow "("

私はそれを理解しています L プレフィックスは、私の式の最初の用語にのみ追加されます。私もこれを試しました:

#define _WIDEN(x) L ## #x

どちらが「動作」しますが、文字列を与えます L"\"file.cpp\" \"(\" \"42\" \")\"" 特に、このマクロが他のマクロと比較して単純であることを考えると、これは明らかにそれほど便利ではありません(私が探しているものではありません)。

だから、私の質問は、MSVC ++の表現全体にそれを適用するにはどうすればよいですか。私はむしろ、それぞれのマクロに2つのマクロを維持する必要があるので、私はむしろ全幅のトークンで2番目の文字列を作成しません。これはあまり便利ではなく、バグにつながる可能性があります。さらに、各文字列の狭いバージョンも必要です。そのため、残念ながら全体の文字列を使用することもオプションではありません。

役に立ちましたか?

解決

C標準(別名ISO-9899:1999 "別名" C99 ")によると、Visual Cは間違っており、GCCは正しいです。その標準州、セクション6.4.5/4:

翻訳フェーズ6では、隣接する文字の任意のシーケンスで指定されたマルチバイト文字シーケンスと幅の広い文字列リテラルトークンは、単一のマルチバイト文字シーケンスに連結されます。トークンのいずれかが幅の広い文字列のリテラルトークンである場合、結果のマルチバイト文字シーケンスは、文字通りの広い文字列として扱われます。それ以外の場合は、文字通りの文字列として扱われます。

したがって、苦情を申し立てることができます。間違いなく、C標準の以前のバージョン(別名「C89」別名C90 "別名「ANSI C」)は、広い文字列のマージと非幅の文字列を義務付けませんでした。 C99は現在10年以上前のものですが、MicrosoftはCコンパイラに適合することに関心がないようです。一部のユーザーは、C ++にはこれらの機能が含まれているため、C ++コードのようにCコードをコンパイルして「C99」機能にアクセスできると報告しています。C++の場合、Microsoftは努力しました。しかし、これはプリプロセッサに拡張されていないようです。

C89方言では、あなたが探していることは不可能だと思います(実際、私はそれをかなり確信しています、そして私は自分のプリプロセッサを書いたので、私は自分が話していることを知っていると思います)。ただし、追加のパラメーターを追加して伝播できます。

#define W(x)          W_(x)
#define W_(x)         L ## x
#define N(x)          x
#define STR(x, t)     STR_(x, t)
#define STR_(x, t)    t(#x)

#define LOCATION_(t)  t(__FILE__) t("(") STR(__LINE__, t) t(")")
#define LOCATION      LOCATION_(N)
#define WLOCATION     LOCATION_(W)

GCCとVisual Cの両方で機能するはずです(少なくとも、Visual C 2005を使用して、私にとっては機能します)。

サイドノート:アンダースコアで始まる名前でマクロを定義しないでください。これらの名前は予約されているため、それらを使用することにより、システムヘッダーまたはコンパイラの将来のバージョンで使用されるいくつかの名前と衝突することができます。それ以外の _WIDEN, 、 使用する WIDEN_.

他のヒント

使用できる2つの広い文字通りの文字列を連結するために

L"wide_a" L"wide_b"

だからあなたは定義することができます

#define WLOCATION WIDEN(__FILE__) L"(" WIDEN(STR(__LINE__)) L")"

(注:MSVC ++でテストされていません)

空の幅の広い文字列を使用するだけで動作するはずです。

 #define WLOCATION L"" __FILE__ "(" STR(__LINE__) ")"
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top