C ++模板,传递带参数化返回类型的函数指针

时间:2014-04-03 04:30:48

标签: c++ templates function-pointers

我想参数化函数的返回值以匹配我传递的函数指针的返回值。我之前只处理过java泛型,所以我很有可能在这里完全遗漏了一些东西。

该功能如下:

<in header>
template <typename T> static T getItems(const char* xpath, T (*getThings)(xpath_node_set*));

<in body>
template <typename T>
T XMLAdapter::getItems(const char* cpath, T(*getThings)(xpath_node_set*)){
    return getThings(head.select_nodes(path));
}

我传入的功能如下:

size_t handler(xpath_node_set* in){
    return in->size();
}

我得到的错误是:

Error   1   error LNK2019: unresolved external symbol \
"public: static unsigned int __cdecl XMLAdapter::getItems<unsigned int>(char const *,unsigned int (__cdecl*)(class pugi::xpath_node_set *))" (??$getItems@I@XMLAdapter@@SAIPBDP6AIPAVxpath_node_set@pugi@@@Z@Z) \
 referenced in function _wmain  C:\Users\Adam\SkyDrive\Documents\proj\ray\ray\ray.obj   ray

是什么给出了?

2 个答案:

答案 0 :(得分:0)

从原型中删除static,它会使您的函数文件成为本地文件(即其他TU不可见)。

通常,函数模板定义应该出现在标题中,而不是单独的.cpp文件。

答案 1 :(得分:0)

如果你的调用者和模板函数不在同一个.cpp文件中,那么模板函数需要在头文件中完全实现(不仅仅是声明),否则你会遇到像这样的链接器错误。

以这种方式思考: 当您在代码上运行编译器时,您实际上正在为每个.cpp文件编译单独的.obj文件。从编译器的角度来看,这些是完全独立的黑盒子。每个.cpp文件都可以并行编译,它们之间没有依赖关系。唯一的依赖是函数声明(在标题中指定),它们表示&#34;是的,是的......其他人正在实现这一点,让链接器抱怨它是否找不到它。&#34;

当你有模板功能时,你真正做的是如何制作一个功能。如果你有Foo&lt; T&gt;并且你想用int&#39; s和字符串来调用它,实际上有两个生成的函数在你的最终二进制文件中完全符号上不同:Foo&lt; int&gt;和Foo&lt; string&gt;。

也就是说,如果你在一个单独的.cpp文件中实现了你的模板函数,那个人试图调用它的专用版本,那么他们就无法做饭了#34;该函数的新版本,包含它们提供的任何模板参数。它们只有一个标题,表示&#34; Foo&lt; T&gt;是其他人实施的功能&#34;安抚链接器。但是你的TemplateImplementation.cpp无法知道它应该生成一个Foo&lt; int&gt;和一个Foo&lt; string&gt;。

这就是为什么您总是会看到作为仅限标头库提供的模板库。如果他们愿意,没有人可以向您发送带有已编译模板函数的库,因为在您调用特定版本之前,他们无法生成函数。