2015-05-28 90 views
3

我感到困惑的實例用下面的例子的點的:點實例化和名稱綁定

#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是實例化的對克< INT點>和2.是實例化的對克<雙>點,因此f(雙)爲克(1.1)可見,然而,輸出是

int 
int 

,如果我在3評價F(INT)的聲明,gcc報告一個錯誤(並不意外),並指出f(t)在4是instantiati的一點在(驚訝!)。

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); 
    ^

任何人都可以清除實例化和名稱綁定的概念嗎?

+0

只有ADL是從POI執行的(並且它不會爲基本類型找到第二個'f',它們沒有關聯的名稱空間)。非定義查找的非ADL部分是從定義的角度執行的。 – dyp

+0

在定義'g'方法之前移動'f(double)'的定義似乎可以解決問題。 – tadman

+0

是的,但我的觀點是ADL應該能夠找到'f(double)',即使它出現在'g'的定義之後。 0x499602D2的解釋似乎是正確的。 –

回答

6

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的關聯的命名空間設置爲全局命名空間。

+0

把'class A {};'放在'void f(A)前面''然後一切正常,謝謝。 –