2013-07-16 128 views
0

我想出了下面的問題(下面的代碼):自動模板專門的模板函數參數

template<class T> 
void printname(const T& t){std::cout<<t<<std::endl;} 

template<class T> 
void applyfunc(const T& t, void (*f)(const T&)){(*f)(t);} 
int main(){ 
    const int a=1; 
    applyfunc(a,printname); 
    getchar(); 
    return 0; 
} 

我的問題是,它與VC++ 8(VS2005)編譯和GCC,鏘(上Ubuntu 12.04) ,但無法使用vC++ 2008 express進行編譯。

這似乎是合法代碼,但我真的不明白爲什麼。

如果有人能解釋它,我會很感激。

假設它是合法的,有沒有什麼辦法可以做類似的工作嗎?

+1

VS2008 Express會出現什麼錯誤? – Praetorian

+0

你在問VS2008爲什麼拒絕代碼,或者爲什麼其他人接受它?*這似乎是合法的代碼,但我真的不明白爲什麼*另外,我不確定有什麼方法可以用類似的方法完成函子的操作。*真的意味着什麼。你想做什麼類似的事情? –

+0

@Praetorian:C2896,C2784不能使用函數模板void(*)(const T&)作爲函數參數 – user2588533

回答

2

我假設你打算使用func代替printname(反之亦然)。我相信這段代碼是合法的,事實上VS2008(也是VS2010;我現在沒有VS2012)很難接受它看起來像一個編譯器錯誤。

回覆:用仿函數類似的東西 - 看看這會爲你:

#include <iostream> 

struct printname { 
    template<class T> 
    void operator()(const T& t) { std::cout<<t<<std::endl; } 
}; 

template<class T, class F> 
void applyfunc(const T& t, F f) { f(t); } 

int main(){ 
    const int a=1; 
    applyfunc(a, printname()); 
    return 0; 
} 
+0

感謝您的回答。我只試過這種情況,當函子本身是模板化的,而不是它的成員函數。傻我。 – user2588533

0

我不知道的問題是,爲什麼它在大多數編譯器或爲什麼它在VS2008失敗。如果問題是前者,我們可以討論這個簡化版本:

template <typename T> 
void f(T const &) {} 

void g(void (*fn)(std::string const&) {} 

g(f); // compiles 
void (*fn)(double const &) = f; 

函數指針是有點特殊的語言,因爲相同的名稱可以指不同的重載。當在代碼中使用函數的名稱時,編譯器無法確定哪些重載是由它自己確定的,因此它將使用表達式的來確定此。在g(f)的情況下,因爲g函數採用void (std::string const&)類型的函數,所以它將將f解析爲f<std::string>,而在初始化fn的情況下,編譯器將解析爲專用f<double>

注意,這是語言的很常用特點:

std::cout << std::endl; 

名稱std::endl指模板:

template <class charT, class traits> 
basic_ostream<charT,traits>& endl(basic_ostream<charT,traits>& os); 

編譯器看到的,這是被稱爲上basic_ostream<char,char_traits<char>>類型的對象std::cout,並且與operator<<的調用相匹配的唯一專業化是其中charT == chartraits == char_traits<char>,並選擇正確的專業化。

+0

感謝您的回答。既然我發佈了我的問題,我已經檢查了標準,並且我的代碼在帖子中是正確的,正如你已經解釋過的。 – user2588533

0

在Visual Studio 2010上,解決方案很簡單,但很細微。您只需在applyfunc(a,printname<int>);行中的打印名稱後添加<int>即可。編譯器需要幫助確定要使用的模板類型。

#include <iostream> 

struct printname 
{ 
    template<class T> 
    void operator()(const T& t) 
    { 
     std::cout << t << std::endl; 
    } 
}; 

template<class T, class F> 
void applyfunc(const T& t, F f) 
{ 
    f(t); 
} 

int main() 
{ 
    const int a=1; 
    applyfunc(a, printname<int>);  // Add <int> here 
    return 0; 
}