ホームページ > バックエンド開発 > C++ > MSVC の 2 フェーズ テンプレートのインスタンス化が C 標準から逸脱しているのはなぜですか?

MSVC の 2 フェーズ テンプレートのインスタンス化が C 標準から逸脱しているのはなぜですか?

Linda Hamilton
リリース: 2024-12-24 14:06:15
オリジナル
182 人が閲覧しました

Why Does MSVC's Two-Phase Template Instantiation Deviate from the C   Standard?

Microsoft Visual C の 2 フェーズ テンプレートのインスタンス化 : 問題は何ですか?

Microsoft Visual C (MSVC) は次のような疑いで批判されています。 2 フェーズ テンプレートのインスタンス化の不正な実装。 C 標準で定義されているこの方法論は、次の 2 つの異なるフェーズで構成されます。

第 1 フェーズ:

  • 基本的な構文と型のチェックを実行します。
  • 内部で使用される非依存名の宣言または存在は検証されません。テンプレート。

第 2 フェーズ:

  • 非依存名を解決し、宣言にバインドします。
  • 名前空間検索を拡張します。最初の宣言以降に蓄積された宣言を持つ依存名の場合フェーズ。

MSVC の欠陥:

MSVC の主な問題は、非依存式の初期 (第 1 フェーズ) ルックアップを実行できないことにあります。代わりに、すべての検索が第 2 フェーズまで延期され、誤った動作が発生します。さらに、MSVC の 2 番目のフェーズでは、非 ADL ルックアップの仕様が正しく尊重されないため、このフェーズ中に拡張すべきではありません。

例:

次のコードを考えてみましょう。 :

int foo(void*);

template<typename T> struct S {
  S() { int i = foo(0); }
};

void foo(int);

int main() {
  S<int> s;
}
ログイン後にコピー

標準準拠のコンパイラは、「foo(0)」呼び出しを次のようにバインドする必要があります。最初のフェーズでは「foo(void*)」。ただし、MSVC は第 2 フェーズでこれを誤って「foo(int)」にバインドし、初期化中にエラーが発生します。

追加の不正レイヤー:

初期化中でも第 2 フェーズでは、MSVC は、非 ADL ルックアップを拡張すべきではないという標準の規定を順守できません。これにより、最初のフェーズでは使用できなかった宣言が含まれることになり、予期しない動作が発生します。

例:

namespace N {
  struct S {};
}

void bar(void *) {}

template <typename T> void foo(T *t) {
  bar(t);
}

void bar(N::S *s) {}

int main() {
  N::S s;
  foo(&s);
}
ログイン後にコピー

ここでは、 'bar(t )」は、第 2 フェーズ中に解決されるにもかかわらず、「void bar(void )」に解決されるはずです。しかし、MSVC はこれを「void bar(N::S s)」と誤って解決し、その実装に欠陥があることを示しています。

結論:

MSVC の 2 つの点フェーズ テンプレートのインスタンス化の実装は C 標準に完全に準拠していないため、非依存式と非 ADL ルックアップの両方を処理するときに誤った動作が発生します。これらの欠陥により、予期しないコンパイル時エラーやプログラムの動作が発生する可能性があります。

以上がMSVC の 2 フェーズ テンプレートのインスタンス化が C 標準から逸脱しているのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート