我希望能够使用如下通用字符串解析函数:
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
答案 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; }