テンプレート プログラミングでstatic_assert
は、プログラマがテンプレート引数の制約をチェックし、制約違反時に人間が読めるエラー メッセージを生成するのに役立ちます。
このコードを考えてみましょう。
template<typename T>
void f(T)
{
static_assert(T(), "first requirement failed to meet.");
static_assert(T::value, "second requirement failed to meet.");
T t = 10; //even this may generate error!
}
私の考えは、最初のエラーが発生した場合、いくつかの要件が満たされていないstatic_assert
ことを意味するため、コンパイルを停止して、最初のエラー メッセージのみを生成する必要があるということです。エラー メッセージのほとんどは、単一の制約違反を示しています。たった 1 つではなく、何百ものエラー メッセージが画面上で非常に恐ろしく見えます。T
static_assert
たとえば、上記の関数テンプレートを次のように呼び出すとします。
f(std::false_type{});
GCC 4.8 は以下を生成します。
main.cpp: In instantiation of 'void f(T) [with T = std::integral_constant<bool, false>]':
main.cpp:16:24: required from here
main.cpp:7:5: error: static assertion failed: first requirement failed to meet.
static_assert(T(), "first requirement failed to meet.");
^
main.cpp:9:5: error: static assertion failed: second requirement failed to meet.
static_assert(T::value, "second requirement failed to meet.");
^
main.cpp:11:11: error: conversion from 'int' to non-scalar type 'std::integral_constant<bool, false>' requested
T t = 10; //even this may generate error!
ご覧のとおり (オンライン)、これはエラーが多すぎます。最初のコードが失敗した場合、コンパイルを続行すると残りのコードも失敗するstatic_assert
可能性が非常に高いのに、なぜコンパイルを続行するのでしょうか? テンプレート プログラミングでは、多くのプログラマーがこのようなカスケード エラー メッセージを望んでいないと確信しています。
次のように、関数を複数の関数に分割し、それぞれが1つの制約のみをチェックすることで、この問題を解決しようとしました。
template<typename T>
void f_impl(T); //forward declaration
template<typename T>
void f(T)
{
static_assert(T(), "first requirement failed to meet.");
f_impl(T());
}
template<typename T>
void f_impl(T)
{
static_assert(T::value, "second requirement failed to meet.");
T t = 10;
}
f(std::false_type{}); //call
これにより、次が生成されます。
main.cpp: In instantiation of 'void f(T) [with T = std::integral_constant<bool, false>]':
main.cpp:24:24: required from here
main.cpp:10:5: error: static assertion failed: first requirement failed to meet.
static_assert(T(), "first requirement failed to meet.");
^
これは大幅な改善です。1 つのエラー メッセージだけで、読みやすく、理解しやすくなっています (オンラインを参照)。
私の質問は、
- コンパイルが最初に停止しないのはなぜ
static_assert
ですか? - 関数テンプレートを分割し、各 function_impl で 1 つの制約をチェックすると、 GCCのみが役立ち、clangは依然として 多くのエラーを生成するため、より一貫した方法で診断を改善する方法はありますか? すべてのコンパイラで機能するものはありますか?