如何链接嵌套模板专业化?

时间:2019-06-12 21:32:09

标签: c++ templates linker-errors

我希望能够使用如下通用字符串解析函数:

Utils::parse::fromString<int>(whatever)
Utils::parse::fromString<float>(whatever)

根据建议here,我将模板专用化从*.ipp移到#include的{​​{1}}文件中进行了分离:

*.hpp

Utils.hpp

#ifndef UTILS_HPP_ #define UTILS_HPP_ #include <string> namespace Utils { namespace parse { template<typename T> T fromString(std::string s); } } #include "Utils.ipp" #endif // UTILS_HPP_

Utils.ipp

现在我有一个带有专用方法的类:

#ifndef UTILS_IPP_ #define UTILS_IPP_ template<> int Utils::parse::fromString<int>(std::string s) { return 42; } template<> float Utils::parse::fromString<float>(std::string s) { return 42.0; } #endif // UTILS_IPP_

Foo.hpp

#ifndef FOO_HPP_ #define FOO_HPP_ #include <string> #include "Utils.hpp" class Foo { public: Foo(); template<typename T> T get(std::string s); }; #include "Foo.ipp" #endif // FOO_HPP_

Foo.ipp

#ifndef FOO_IPP_ #define FOO_IPP_ #include <string> template<typename T> T Foo::get(std::string s) { return Utils::parse::fromString<T>(s); } #endif // FOO_HPP_

test.cpp

如果我仅直接使用#include <iostream> #include <string> #include "Utils.hpp" #include "Foo.hpp" // Custom template specialization template<> char Utils::parse::fromString<char>(std::string s) { return 'c'; } int main() { // Calling `fromString` directly - this works! const std::string whatever = "whatever"; std::cout << Utils::parse::fromString<int>(whatever) << std::endl; std::cout << Utils::parse::fromString<char>(whatever) << std::endl; // Calling `fromString` via `Foo` - linking error! Foo foo; std::cout << foo.get<int>(whatever) << std::endl; return 0; } ,它可以正常工作。但是,如果我使用fromString,则会出现“多个定义”链接错误:

Foo

1 个答案:

答案 0 :(得分:1)

模板函数不需要inline来避免多个定义,而专业化则像常规函数一样。

您必须添加它:

template <>
inline int Utils::parse::fromString<int>(std::string s) { return 42; }

template<>
inline float Utils::parse::fromString<float>(std::string s) { return 42.0; }