2011-12-23 218 views
4

爲什麼編譯器找不到匹配read1?我沒有看到read1read2之間的區別;嵌套typedef模板是否存在類似Foo類中的限制?C++模板typedef作爲模板函數參數

template<typename T> 
class Handle{}; 

class Foo{ 
public: 
    typedef Handle<Foo> Handle; 
}; 


template<typename T> 
void read1(typename T::Handle){} 

template<typename T> 
void read2(Handle<T>){} 


int main(int argc, char** argv) 
{ 
    Foo::Handle f1;  
    read1(f1); 

    Foo::Handle f2; 
    read2(f2); 
} 

G ++編譯器的輸出,(G ++ 4.4.5)

g++ -c -I. main1.cpp 
main1.cpp: In function ‘int main(int, char**)’: 
main1.cpp:37: error: no matching function for call to ‘read1(Handle<Foo>&)’ 
+0

我刪除了多餘的'Internal'命名空間,保持示例簡潔。 – Xeo 2011-12-23 00:36:44

+0

使用G ++ 4.4.5編輯中斷代碼''g ++ -c main.cpp main.cpp:8:錯誤:'typedef類聲明'句柄 Foo :: Handle' main.cpp:3:error:changes在'int main(int,char **)'函數中:''' &)'' – 2011-12-23 01:40:23

回答

4
Foo::Handle f1;  
read1(f1); 

傳遞給read1的類型是Handle<Foo>而不是Foo。

模板不是繼承。 Handle<Foo>是一個不同於Foo的類,因此沒有Handle<Foo>::Handle

3
template<typename T> 
void read1(typename T::Handle) 
{ 
} 

首先,你將永遠無法調用此函數不提供顯式模板參數像read1<Foo>(f1)。請閱讀SFINAE

二,編譯器有沒有問題想知道什麼是T是?它將不得不測試所有可能編寫的類的所有嵌套typedef。聽起來不可能?它是。

+2

它不需要測試你可能寫的每個類;它只需要測試在read1調用點定義的那些類。可能的(甚至與編譯器處理模板所需的某些事情相比,很容易),但不是按照標準完成的。 – 2011-12-23 01:31:35

+0

爲什麼可以找到像read2那樣的參數?它只是需要測試Foo沒有其他類型 – 2011-12-23 01:37:53

+0

它不僅需要測試在該點定義的所有類,還要測試所有可能的模板實例(儘管可能以模板形式)。但是,它將如何解決歧義?通常情況下,程序員必須修復這些問題,但在這種情況下,一些完全不相關的代碼更改(不同的名稱空間和全部)會導致不確定性,因此讓程序員修復這些並不是真正的選擇。 @José:在這個簡單的例子中,它可能只需要測試foo,但是大部分的表情更加複雜,並且大多數時候不起作用的語言特徵並不是那麼受歡迎 – Grizzly 2011-12-23 02:24:46