相棒、私は科学研究中に質問に出くわしました.コンパイル時に評価値を出力することは可能ですか? コンパイル時にコンパイラが式を評価することは確かですが、ポイントは、コンパイル中に評価された値をどのように出力できるかということです。1 つの方法はエラーを強制することですが、あまり洗練されていないようです。TMPを使いたいのですが、可能ですか?ありがとう。
3 に答える
整数定数式の値を確認したい場合、デバッグ目的で値を確認する簡単な方法は、その値でエラーを作成することです。例えば:
template <int> struct constexpr_debugger;
int main() {
const int i0(4), i1(17);
constexpr_debugger<i0 + i1> debug;
}
このコードをコンパイルすると、メッセージが表示されます
constexpr_debugger.cpp: In function ‘int main()’:
constexpr_debugger.cpp:5:37:error: aggregate ‘constexpr_debugger<21> debug’ has incomplete type and cannot be defined
constexpr_debugger<i0 + i1> debug;
^
値に興味があってもコードをコンパイルしたい場合、私が知っている最善の方法は、未使用の変数などに基づいて警告メッセージを作成することです。標準では警告は決して必要とされないため、警告が表示される場合に使用されるコンパイラとフラグに少し依存します。gccとclangでテストすると、残念ながら、上記のクラス テンプレートが単純に定義されている場合、コンパイラはテンプレート パラメーターの値を表示しないことがわかります。次のコードは、[現在] コンパイラが診断で報告する内容が異なることを示しています。
template <int>
void constexpr_debugger()
{
int debug;
}
int main() {
const int i0(4), i1(17);
constexpr_debugger<i0 + i1>();
}
gcc は、テンプレート パラメーターを含む関数に言及しているため、使用されていないことを警告するときに目的の値を示しますdebug
。clang についても警告しdebug
ますが、問題が発生するテンプレートのインスタンス化については言及していません。使用しているコンパイラで動作する形式の何かが必要になります (おそらく、使用しているコンパイラのバージョンに合わせて調整する必要があります)。
C++11以降constexpr
、コンパイル時にその式を評価できるようにするために使用できます
例 :
constexpr int sqr(int x)
{
return x*x;
}
int a[sqr(4)]; //Compiles with C++11 and a has 16 elements.
評価された式を表示するには、テンプレートのメタプログラミングを使用します
template<unsigned int n>
struct dummy ;
int main() {
char<dummy1<dummy<1 + 55-2>::dummy2>()); //Obliviously wrong
return 0;
}
コンパイラからのエラー:
error: incomplete type 'dummy<54u>' used in nested name specifier
コンパイル エラーや警告を使用したくない場合は、型情報をオブジェクト ファイルのシンボルに入れることができます。次のプログラムは、コンパイル時のリストに対してそれを行います。
// Just define the types we need to construct lists.
template <typename Head, typename Tail> struct Cons {};
struct Nil {};
// This is what you want to output.
using MyOutput = Cons<int, Cons<float, Cons<char, Nil>>>;
// Template function declaration.
template <typename TheOutput>
void MyOutputFunc () {}
// Explicitly instantiate the template function with the desired output.
template void MyOutputFunc<MyOutput> ();
出力の取得はコンパイラであり、おそらく OS 固有です。以下は、Linux 上の g++ でこれを示しています。
$ g++ -c -std=c++11 a.cpp
$ nm a.o | grep MyOutputFunc
0000000000000000 W _Z12MyOutputFuncI4ConsIiS0_IfS0_Ic3NilEEEEvv
$ nm a.o | grep MyOutputFunc | cut -d ' ' -f3 | c++filt
void MyOutputFunc<Cons<int, Cons<float, Cons<char, Nil> > > >()
次のような型でラップすることにより、整数を出力できます。
template <typename T, T value>
struct WrapValue {};
using MyOutput = WrapValue<int, 15>;
これは、デバッグではなく、さまざまなサポート情報を取得するのに役立ちます。たとえば、この方法の私の使用例は、一部のマイクロコントローラー ソフトウェアの構成オプションに関連していました。コンパイル時の出力は、テンプレート プログラムが構成オプションを EEPROM メモリにマップした方法です。