2011-12-09 57 views
1

剛纔我正在學習函數模板,我想研究一下函數模板實例化的一些規則。所以我寫了下面的代碼:C++ - 函數模板實例化的規則

#include <iostream> 

template <typename> 
int check(int x) { 
    return x * 2; 
} 

int main() { 
    std::cout << check<double>(10) << std::endl; // #1 
    std::cout << check<>(10) << std::endl;   // #2 
    std::cout << check(10) << std::endl;   // #3 
    return 0; 
} 

的線#1,#2,#3不編譯都在一起,每一個嘗試,我離開只是其中之一和評論休息。 因此,當啓用#1時,我沒有編譯錯誤,並打印正確答案「20」。據我所知,「檢查<」double「>」調用模板實例化機制,因此「int check(int)」函數是真正創建的(模板參數的類型沒有任何影響)。 當#3啓用時,我有一個編譯錯誤「錯誤:沒有匹配函數調用'檢查(int)'」,這是合理的,因爲我試圖調用「check(int)」不存在的功能。我的問題是關於#2的情況:在這種情況下,我得到相同的「錯誤:沒有匹配函數調用'檢查(int)'」。不應該調用「檢查<」(10)「觸發器模板實例化機制以及?

+0

「_S不應該調用」check <>(10)「觸發器模板實例化機制?_」你的問題的答案是:用什麼參數? – curiousguy

回答

0

如果您沒有傳遞模板參數,它就相當於在沒有模板參數的情況下查找函數(即它不會實例化模板)。增加的<>在這種情況下意味着什麼,因爲沒有超載。

由於函數你有沒有實際使用任何東西的模板和編譯器,因此不能推斷出類型T,但如果你把它寫這樣的:

template <typename T> 
T check(T x) { 
    return x * 2; 
} 

然後所有3個案例將工作,因爲它推斷類型T。有關更多說明,請參閱https://stackoverflow.com/a/797632/888641

注意:您可以使用typenameclass,他們在這裏做完全相同的事情。

+0

謝謝!我添加「<>」的原因是在Vandevoorde的「C++模板:完整的Guilde」一書中寫道,像「check <>」這樣的調用將強制使用函數的模板版本(它在函數模板的上下文中提到過)超載) – mkostya

+0

這並不意味着什麼。如果你有一個重載,它會喜歡模板,而不是其他匹配的重載。 –

+0

所以如果沒有超載,它只是意味着什麼? – mkostya

0

我不得不說,平時模板不走那條路:(

試試這個:

template<typename T> 
T check(T x){ 
    return x*2; 
} 
0

#2將是有效的,如果模板參數可以推斷

#include <iostream> 

template <class T> 
void foo(T t) 
{ 
    std::cout << "Template " << t << '\n'; 
} 

void foo(int n) 
{ 
    std::cout << "Not template " << n << '\n'; 
} 

int main() 
{ 
    foo(10); //calls non-template function 
      //because matching non-template preferred over function templates 

    foo<>(10); //calls the template function, empty brackets indicate you want 
       //the template overload, type is deduced from passed argument. 

} 

另一種可能性,如果函數模板具有默認參數(僅在C++ 11中合法)。

template <class T = void> 
int foo() 
{ 
    return 10; 
} 

int main() 
{ 
    return foo<>(); //same as foo<void>(); 
} 
+0

謝謝,這使得它更清晰。 – mkostya

0

唯一的模板實例,你會得到的是

check<double>(10) 

別人不實例化的模板。也爲函數模板的全功率包括然後,使用模板參數推導的功率模板參數作爲

template<typename T> 
T check(T x) { 
    return x*2; 
} 

你可以叫

check(10.0); // instantiates check<dobule> 
check(3);  // instantiates check<int> 

a = MyObject(); 
check(a);   // instantiates check<MyObject> 
1

你不將任何模板參數放入<>中。編譯器如何知道實例化哪個模板函數?請注意,您的模板函數是:

template <typename> 
int check(int x) 

如果你把它改成這樣:

template <typename T> 
int check(T x) 

然後檢查<>(10)應該是罰款,因爲編譯器可以知道從參數類型。