2012-11-20 11 views
12

コンパイル時にconstexprまたは#defineの値を出力する方法はありますか?私はstd :: coutはコンパイル時に相当する、またはstatic_assert C++でのコンパイル時定数値の文字列化11

template <int v> 
struct display_non_zero_int_value; 

template <> 
struct display_non_zero_int_value<0> { static constexpr bool foo = true; }; 

static constexpr int v = 1; 

static_assert(v == 0 && display_non_zero_int_value<v>::foo, "v == 0"); 
ような何かを行うことによって、少なくともgccの上、 constexpr秒でいくつかの基本的なコンパイル時の印刷を行うことができます:私は std::cout <<の同等、または編集
constexpr int PI_INT = 4; 
static_assert(PI_INT == 3, 
       const_str_join("PI_INT must be 3, not ", const_int_to_str(PI_INT))); 

ような何かをするためにいくつかの方法をしたいです

これは私にerror: incomplete type ‘display_non_zero_int_value<1>’ used in nested name specifier static_assert(v == 0 && display_non_zero_int_value<v>::foo, "v == 0");を与えます。私は

constexpr int PI_INT = 4; 
PRINT_VALUE(PI_INT) 

ような何かをし、関係のエラーメッセージを得ることができるように、これを一般化することができますマクロを書くための方法はあります(ICPCは、他の一方で、あまり有用である、とだけerror: incomplete type is not allowedを言います) 4、何とか?

+2

私は手元に証拠がないのでこれを投稿しませんが、過去にこれをやろうとしたことを覚えています。そして、標準ではstatic_assertが文字列リテラルを取らなければならないと言います。代わりにconstexpr式を使用しないでください。ごめんなさい。 – je4d

+0

あなたの修正は 'static_assert'を全く使っていないことに注意してください。合格または不合格だけを行うコンストラクトの基本的なアイデアを改革しています。 「印刷」を行うこともテストを実行しなければならないので、SFINAEを使用して問題全体を解決する必要があります。 – Potatoswatter

答えて

11

§7/ 1 [dcl.dcl]に宣言するために与えられた文法を引用:

static_assert-declaration:

static_assert (constant-expression , string-literal) ;

標準は、それはあなたが運の出ているので、文字列リテラルでなければならないと言います。 constexpr関数を使用してエラーメッセージを構成することはできません。

しかし、あなたがそこに入る文字列リテラルを生成するのに好きなプリプロセッサの魔法を使用することはできます。 OPと更新問題でコメントするに応じて

error: static assertion failed: "PI_INT must be 3, not 4"


編集

#define PI_INT 4 
#define pi_err_str_(x) #x 
#define pi_err_str(x) pi_err_str_(x) 
#define pi_int_err "PI_INT must be 3, not " pi_err_str(PI_INT) 

static_assert(PI_INT == 3, pi_int_err); 

出力:PI_INTではなくconstexpr intのに#defineである場合、あなたはこのようなものを使用することができます

Is there a way to write a macro that can generalize this so that I can do something like ... and get an error message that involves 4, somehow?

確かに、少し前処理や魔法を使用すると、コンパイラ固有のエラーメッセージの動作に依存することに満足していると仮定すると、それを一般化することができます他のコンパイラについては

#define strcat_(x, y) x ## y 
#define strcat(x, y) strcat_(x, y) 
#define PRINT_VALUE(x) template <int> struct strcat(strcat(value_of_, x), _is); static_assert(strcat(strcat(value_of_, x), _is)<x>::x, ""); 

constexpr int PI_INT = 4; 
PRINT_VALUE(PI_INT) 

stackoverflow/13465334.cpp:20:1: error: incomplete type ‘value_of_PI_INT_is<4>’ used in nested name specifier

、私はあなたがぶっきらぼうに何ができるかを知っている、しかし、あなたはありませんブーストのstatic_assert.hppのコピーを見て、そこに使用されているトリックのどれかを使って、評価されたテンプレートargをプリントすることができるかどうかを調べることができます。

+0

それは私の質問の最後の3分の2に答えます。コンパイル時に 'constexpr'値を出力することに関する最初の3分の1は、それほど明白ではありません。私が作った編集を見てください。 –

+0

テンプレートスコープ内での印刷の場合、これをブロックスコープで動作させる方法はありますか? – mxmlnkn

関連する問題