2012-02-15 20 views
1

這個程序(用gcc 4.6.2)爲什麼我會得到鏈接錯誤:模板方法不是實例

#include <iostream> 

// prints something; 
// the template doesn't add anything 
template <typename T> 
struct Printer 
{ 
    void print() 
    { 
     std::cout << "Printer::print" << std::endl; 
    } 
}; 

// this is an actual template 
// calls the method indicated by the second template argument 
// belonging to the class indicated by the first template argument 
template < typename U, void(U::*func)()> 
struct Caller 
{ 
    void call(U obj) 
    { 
     (obj.*func)(); 
    } 
}; 

// just a wrapper 
template<typename V> 
struct Wrapper 
{ 
    void call_caller_on_printer() 
    { 
     Printer<int> a_printer; 
     Caller<Printer<int>, &Printer<int>::print> caller; 
     caller.call(a_printer); 
    } 
}; 

int main() 
{ 
    Wrapper<int> the_wrapper; 
    the_wrapper.call_caller_on_printer(); 

    return 0; 
} 

鏈接器抱怨打印機​​打印::是一個未定義的參考。但是,如果您將Wrapper設置爲非模板(該模板不會在其中添加任何內容),則它可以工作。打印機的打印方法似乎沒有被實例化。這是爲什麼?

+2

FWIW,適用於[GCC 4.3.4(http://ideone.com/pR7y6 )和MSVC10,在[GCC 4.5.1](http://ideone.com/6VDTp)上失敗。看起來像是對我的迴歸。 – ildjarn 2012-02-15 23:20:56

回答

0

我對GCC 4.5.1有一個問題that looks similar(是的,它看起來像一個迴歸)。

在我的情況下,它有助於明確地將指針轉換爲所需的類型,以使GCC 4.5.1吞下該代碼。嘗試在這裏做同樣的事情。即

Caller<Printer<int>, static_cast<void (Printer<int>::*)()>(&Printer<int>::print)> caller; 

(未經測試,順便說一句,鑄造甚至語法上有效的,否則在這裏一元函數可能幫助?)

+0

不幸的是,這個建議不會編譯(作爲模板參數傳遞的'static_cast'是問題)。然而,總的想法(以某種方式操縱違規的'Printer :: print')是有用的,因爲它可能會迫使編譯器出於其他原因實例化它。考慮到它的地址的訣竅:'void(Printer :: * x)()=&Printer :: print'; – Rekr 2012-02-16 14:58:21