1つ目、たとえば配列の各要素にアクセスするコードってこう書くことがありますよね?
for(int i; i
namespace NS1{
struct A{};
template
void func(A){
std::cout
void func(int){
std::cout(a); //これは関数が見つからずエラー
NS1::func(a); //これは当然問題ない。
NS2::func(10); //これも問題ない。
//ここで、using宣言を用いて… (※)
using NS2::func;
func(a); //さっきは通らなかったのに…通る。もちろんNS1::funcが選ばれる。
NS1::func(a); //これは当然問題ない。
func(10); //これは問題ない。
}
{※の前}
func(a) をコンパイラが解釈するときに、funcが不可視(少なくともmainから見える位置にはfuncという識別子はない)ため、どう解釈すべきかが曖昧なためコンパイルエラー
※曖昧 … func(a)というのは、テンプレート関数の呼び出しほかに、(func (a)という比較演算とも解釈できるため、funcが何者かが判別できないとこれを解釈できない。
{※の後}
func(a) をコンパイラが解釈するとき、using宣言によってNS2::func(これはテンプレート関数)が見えるため、これを関数呼び出しと解釈し、呼び出し関数の解決に走る。そこで、実引数依存の名前探索(ADL) - Wikipediaが行われ、NS1::funcが呼び出し関数の候補に加えられる。その結果、func(a)はNS1::funcの呼び出しへと解決される。
これは驚きです。using宣言でこうも変わるものか…