4

次の例では、インスタンス化のポイントについて混乱しています。

#include <iostream>

void f(int){std::cout<<"int"<<std::endl;}//3

template <typename T>
void g(T t)
{
    f(t);//4
}

void f(double){std::cout<<"double"<<std::endl;}

int main()
{
    g<int>(1);//1.point of instantiation for g<int>
    g<double>(1.1);//2.point of instantiation for g<double>, so f(double) is visible from here?
    return 0;
}

f は従属名であり、1. は g< int > のインスタンス化のポイントであり、2. は g< double > のインスタンス化のポイントであるため、g(1.1) では f(double) が表示されますが、出力はは

int
int

そして、3 で f(int) の宣言をコメントすると、gcc はエラーを報告し (驚きではありません)、4 で f(t) がインスタンス化のポイントであると指摘します (驚き!!)。

test.cpp: In instantiation of ‘void g(T) [with T = int]’:
test.cpp:16:10:   required from here
test.cpp:9:5: error: ‘f’ was not declared in this scope, and no    declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
  f(t);
     ^

インスタンス化のポイントと名前バインディングの概念を明確にしてくれる人はいますか?

4

1 に答える 1

9

f(t)依存する非修飾関数呼び出し式であるため、定義コンテキスト内で見つかった関数と ADL を介して見つかった関数のみが候補になります。f(int)は定義コンテキスト内では表示されますが、 では表示されないf(double)ため、オーバーロードの解決はf(int)両方の呼び出しに対して に解決されます。

f(double)組み込み型には関連付けられたクラスまたは名前空間がないため、ADL で見つけることができません。クラス型の引数を渡し、fこの型を取るオーバーロードがあった場合、ADL はそれを見つけることができます。例えば:

void f(int);

template <typename T>
void g(T t)
{
    f(t);
}

class A {};
void f(double);
void f(A);

int main()
{
    g(1);   // calls f(int)
    g(1.1); // calls f(int)
    g(A{}); // calls f(A)
}

f(A)が呼び出されるのは、それがグローバル名前空間にあり、Aの関連付けられた名前空間セットがグローバル名前空間であるためです。

于 2015-05-28T18:34:43.243 に答える