在我的代码中,通常我必须编写一个采用“类路径”类型的函数,也就是说,我可以转换为boost::filesystem::path
的函数,例如
QString
std::string
const char *
在A.hpp
struct A
{
template <typename PathLike>
void myFunction(PathLike path);
};
在A.cpp
template <typename PathLike>
void A::myFunction(PathLike path)
{
boost::filesystem::Path p = convertToBoostPath(path);
//do something...
}
//Explicit instantiations needed
template void A::myFunction(string);
template void A::myFunction(QString);
template void A::myFunction(char const *);
//....
问题是,如果我想在不同的函数B
中做同样的事情,我需要重新添加显式实例化。也许我采取了错误的做法。
不是编写一个接受任何PathLike
的模板函数而且还能完成真正的工作,而是编写一个模板函数,它接受任何PathLike
,如图所示将其转换为boost::filesystem::Path
,然后调用非模板函数(其定义可以在.cpp中)这将做真正的工作。
在A.hpp
:
class A
{
public:
template <typename PathLike>
void myFunction(PathLike path);
private:
void myFunctionImpl(boost::filesystem::Path path);
};
template <typename PathLike>
void A::myFunction(PathLike path)
{
myFunctionImpl(convertToBoostPath(path));
}
在A.cpp
:
void A::myFunctionImpl(boost::filesystem::Path path)
{
// do something...
}
这具有额外的好处,即错误使用接口会导致编译器错误,而不会导致链接器错误。
如何创建一个类PathLike
并使用它:
class PathLike
{
public:
explicit PathLike(const QString& path) : mPath(convertToBoostPath(path)) {}
explicit PathLike(const std::string& path) : mPath(convertToBoostPath(path)) {}
explicit PathLike(const char* path) : mPath(convertToBoostPath(path)) {}
PathLike(const boost::filesystem::path& path) : mPath(path) {}
const boost::filesystem::path& get() const { return mPath;}
operator const boost::filesystem::path&() const { return mPath;}
private:
boost::filesystem::path mPath;
};
(我标记其他构造函数显式提升filesystem::path
,但由你来添加/删除explicit
)。
然后:
struct A
{
void myFunction(PathLike path)
{
boost::filesystem::path p = path;
//do something...
}
};
为一组类型显式实例化函数模板的一种方法是获取每个函数实例化的地址。例如。:
template<class... Ts>
void instantiate_myFunction() {
auto f = [](auto&&) { return 1; };
auto initializer_list = { f(&A::myFunction<Ts>)... };
static_cast<void>(initializer_list);
}
int main() {
instantiate_myFunction<std::string, char const*>();
}