C++ 一组类型的显式实例化
在我的代码中,通常我必须编写一个采用“类似路径”类型的函数,例如,我可以将其转换为C++ 一组类型的显式实例化,c++,templates,metaprogramming,C++,Templates,Metaprogramming,在我的代码中,通常我必须编写一个采用“类似路径”类型的函数,例如,我可以将其转换为boost::filesystem::Path QString std::string const char* 等等 在A.hpp中 struct A { template <typename PathLike> void myFunction(PathLike path); }; 结构A { 样板 void myFunction(类路径路径); }; 在A.cpp中 template
boost::filesystem::Path
QString
std::string
const char*
- 等等
struct A
{
template <typename PathLike>
void myFunction(PathLike path);
};
结构A
{
样板
void myFunction(类路径路径);
};
在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 *);
//....
模板
void A::myFunction(类路径路径)
{
boost::filesystem::Path p=convertToBoostPath(Path);
//做点什么。。。
}
//需要显式实例化
模板void A::myFunction(字符串);
模板void A::myFunction(QString);
模板void A::myFunction(char const*);
//....
问题是,如果我想在不同的函数
B
中执行相同的操作,我需要重新添加显式实例化。也许我采取了错误的方法。与其编写一个接受任何路径的模板函数,还不如编写一个接受任何路径的模板函数,将其转换为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));
}
void A::myFunctionImpl(boost::filesystem::Path 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*>();
}
模板
void实例化_myFunction(){
自动f=[](自动&&){return 1;};
自动初始值设定项\u list={f(&A::myFunction)…};
静态转换(初始值设定项列表);
}
int main(){
实例化_myFunction();
}
创建一个类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;
};
(我将其他构造函数标记为显式,以提升文件系统::路径
,但添加/删除显式
则取决于您)
然后:
struct A
{
void myFunction(PathLike path)
{
boost::filesystem::path p = path;
//do something...
}
};
为什么不在头文件中定义函数呢?如果需要,您可以使用SFINAE来约束类型。您必须为每个要执行此操作的函数模板编写不同的实例化\u myFunction
,对吗?据我所知,函数模板唯一能做的就是实例化它(与类模板相反,类模板可以作为模板参数传递),不幸的是…@MaxLanghof这是真的,使用Path
class是正确的解决方案,依我看。