4

次のコードは、GCC 4.6 では受け入れられません。

void F(int x,char y)
{
}
template<typename T>
void G(T t)
{
    F(t);
}
void F(int x)
{
}

int main()
{
    G(5);
    return 0;
}

それはすべきですか?

そうでない場合、誰かが回避策の良いアイデアを持っていますか? これが発生する現実世界のシナリオでは、G が特定の種類の問題を解決するためのライブラリの一部であり、F と呼ばれるユーザー提供のヘルパー関数が必要です。ただし、さまざまな種類の問題では、F はさまざまな数のパラメーターを受け取ります。ライブラリには、F のサンプル実装がいくつか付属しています。

何が起こっているかというと、クライアントが使用する #include-order によっては、テンプレート宣言時に F の「間違った種類」のみが表示される可能性があり、GCC はユーザーが提供する正しい F を待たずにあきらめます。が定義されています。これは、正しい F が定義された後にテンプレートのインスタンス化が行われるにもかかわらずです。

更新: はい、F のすべての宣言が G の前に発生する場合、または F のすべての宣言が G の後に発生する場合に機能することはわかっています。ただし、それはあまり役に立ちません。

更新: この最小限の例が適用されたコードでは、F は実際には「読み取り」と呼ばれます。read の最初の宣言は、2 番目の宣言とはまったく関係ありません。最初の宣言は 1 つのヘッダー ファイルにあり、2 番目の宣言は別のヘッダー ファイルにあります。特に「読み取り」のバージョンが互いに何の関係もない場合、インクルードファイルの順序に関して「奇妙な」ルールを導入したくありません。

4

4 に答える 4

4

インスタンス化では、引数に依存するルックアップのみが行われます。タイプが名前空間に存在する引数を使用して、ケースを修正できますF

void F(int x,char y)
{
}
template<typename T>
void G(T t)
{
    F(t);
}
void F(int x)
{
}

template<typename T>
struct wrapper {
 operator T() const { return t; }
 T t;
};

template<typename T> wrapper<T> make_wrapper(T t) {
  wrapper<T> w = { t };
  return w;
}

int main()
{
    G(make_wrapper(5));
    return 0;
}
于 2012-11-04T22:13:39.430 に答える
1

void F(int x)考えられる回避策の 1 つは、 の宣言が の宣言の前に使用可能であることを確認することです。template<typename T> void G(T t);

void F(int x);

template<typename T> void G(T t) { .... }

あなたの例では、F(int)従属名なので、2 フェーズ ルックアップの第 2 フェーズでルックアップされます。ただし、ルックアップのルール。ドラフト n3337 の §14.6.4 で指定されているように、テンプレートの定義の時点で、または関数の引数の型に関連付けられた名前空間で名前が表示される必要があることを指定します (引数依存のルックアップ)。

従属名の解決では、次のソースからの名前が考慮されます。

— テンプレートの定義時に表示される宣言。

— インスタンス化コンテキスト (14.6.4.1) と定義コンテキストの両方からの関数引数の型に関連付けられた名前空間からの宣言。

したがって、代替の回避策は、関数を の名前空間に持ち込むことですT

于 2012-11-04T21:49:43.093 に答える
0

F(int)のオーバーロードを配置してみてください。 G

void F(int x) {}

template <typename T> void G(T t) { F(t); } // works

関数は巻き上げられません。それらを使用する前に、プロトタイプを作成するか定義する必要があります。

于 2012-11-04T21:49:39.363 に答える
0

そうでない場合、誰かが回避策の良いアイデアを持っていますか?

そのテンプレートを定義した時点でF()、コンパイラに知られているのは のみでありvoid F(int x,char y)、これは明らかに での使用法と一致しませんG(T t)

解決策は簡単です: を定義するvoid F(int x) 前に定義または宣言しtemplate<typename T> void G(T t)ます。

于 2012-11-04T21:50:55.577 に答える