2012-02-15 65 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