41

g++ 4.6.3 (現在、ubuntu 12.04 のデフォルト パッケージ) をフラグ c++0x と共に使用していますが、これに出くわしました:

template <typename T>
inline T getValue(AnObject&)
{
    static_assert(false , "this function has to be implemented for desired type");
}

コンパイルエラーで:

static_assertion failed "this function has to be implemented for the desired type"

この関数はまだどこにも呼び出していませんが

それはg ++のバグですか?この関数は、コードのどこかで呼び出された場合にのみインスタンス化されるべきではありません。

4

4 に答える 4

63

標準は [temp.res]/8 で言う

有効な特殊化を生成できるテンプレート定義に対しては、診断は発行されません。テンプレート定義に対して有効な特殊化を生成できず、そのテンプレートがインスタンス化されていない場合、テンプレート定義は不適切な形式であり、診断は必要ありません。... [ 注:テンプレートがインスタンス化されている場合、この標準の他のルールに従ってエラーが診断されます。これらのエラーがいつ診断されるかは、実装の品質の問題です。— 終了注記]

コンパイルされる関数テンプレートをインスタンス化する方法がないため、テンプレート定義の形式が正しくないため、インスタンス化されていない場合でも、コンパイラはそれを拒否できます (必須ではありません)。

次のように機能させることができます。

template<typename T>
struct foobar : std::false_type
{ };

template <typename T>
inline T getValue(AnObject&)
{
    static_assert( foobar<T>::value , "this function has to be implemented for desired type");
}

foobarインスタンス化されるまで、 hasの特殊化があるかどうかわからないため、コンパイラは関数テンプレートをすぐに拒否できませんvalue == true。インスタンス化されると、関連する特殊化foobar<T>がインスタンス化され、静的アサーションは必要に応じて失敗します。

于 2013-02-01T00:11:09.520 に答える
33

これは、条件がテンプレート パラメーターにまったく依存しないためです。したがって、コンパイラはそのテンプレートをインスタンス化する前でもそれを評価でき、評価がfalse.

つまり、これはバグではありません。多くのことは、テンプレートがインスタンス化された後にしかチェックできませんが、コンパイラーがその前に実行できる妥当性チェックは他にもあります。これが、たとえば C++ に 2 フェーズの名前検索がある理由です。コンパイラは、発生する可能性が 100% のエラーを見つける手助けをしようとしているだけです。

于 2013-01-31T23:56:27.290 に答える
5

これは実際にはコメントですが、コード例が必要です。

神聖な標準の文言はstatic_assert、その効果をインスタンス化されたコードに限定しません。

ただし、コード

template <typename T>
inline T getValue(int&)
{
    typedef char blah[-1];  // Common C++03 static assert, no special semantics.
}

int main()
{}

また、MinGW g++ 4.7.2 でのコンパイルに失敗し、これが問題を強調しています。

答えは、g++ が正しく、これに対してコンパイル エラーを生成しない Visual C++ 11.0 が間違っているということだと思いますが、Holy Standard の節に関して関連する分析を提供するのは難しいでしょう

コンパイラの違いによる実際的な結果として、現時点では動作に依存できません。

于 2013-02-01T00:09:37.243 に答える