C++ C++;使用if语句的模板实例化
我想写一个C++ C++;使用if语句的模板实例化,c++,C++,我想写一个sort函数,它接受包含多个容器的可变参数:voidsort(C&C,Rest&…Rest) 第一个错误来自这样一个事实:在编译器实例化模板时,它编译整个函数,而不仅仅是满足条件的if分支 这意味着当您将一个向量传递给sort时,它将被C实例化为std::vector,但随后尝试编译(注意:不执行),C.sort()。在本例中,std::vector没有sort()成员。这就是为什么会出现这个错误。因为编译器将尝试实例化整个模板(即用实际类型替换C,并编译每一行) 要修复它,您需要修改
sort
函数,它接受包含多个容器的可变参数:voidsort(C&C,Rest&…Rest)
第一个错误来自这样一个事实:在编译器实例化模板时,它编译整个函数,而不仅仅是满足条件的
if
分支
这意味着当您将一个向量传递给sort
时,它将被C
实例化为std::vector
,但随后尝试编译(注意:不执行),C.sort()
。在本例中,std::vector
没有sort()
成员。这就是为什么会出现这个错误。因为编译器将尝试实例化整个模板(即用实际类型替换C
,并编译每一行)
要修复它,您需要修改模板,使其实例化一个完全针对您的类型编译的版本<代码>标准::如果在这里是一个潜在的解决方案,则启用\u:
template<typename C, typename std::enable_if<is_list<C>::value>::type >
void sort(C &c){
c.sort();
}
template<typename C, typename std::enable_if<!is_list<C>::value>::type* = nullptr>
void sort(C &c){
std::sort(c.begin(), c.end());
}
模板
无效排序(C&C){
c、 排序();
}
模板::类型*=nullptr>
无效排序(C&C){
排序(c.begin(),c.end());
}
第一个错误来自这样一个事实:在编译器实例化模板时,它编译整个函数,而不仅仅是满足条件的
if
分支
这意味着当您将一个向量传递给sort
时,它将被C
实例化为std::vector
,但随后尝试编译(注意:不执行),C.sort()
。在本例中,std::vector
没有sort()
成员。这就是为什么会出现这个错误。因为编译器将尝试实例化整个模板(即用实际类型替换C
,并编译每一行)
要修复它,您需要修改模板,使其实例化一个完全针对您的类型编译的版本<代码>标准::如果在这里是一个潜在的解决方案,则启用\u:
template<typename C, typename std::enable_if<is_list<C>::value>::type >
void sort(C &c){
c.sort();
}
template<typename C, typename std::enable_if<!is_list<C>::value>::type* = nullptr>
void sort(C &c){
std::sort(c.begin(), c.end());
}
模板
无效排序(C&C){
c、 排序();
}
模板::类型*=nullptr>
无效排序(C&C){
排序(c.begin(),c.end());
}
一旦您解决了所看到的问题,您的代码就出现了另一个问题 您没有处理递归的终端情况 我还添加了完美的转发 如果您使用的是c++17,如果愿意,可以使用constexpr
template<typename C, typename...Rest>
void sort(C &c, Rest&& ... rest){
if constexpr (is_list<C>::value == true) c.sort();
else std::sort(c.begin(), c.end());
if constexpr (sizeof...(rest) >= 1) // empty case
sort(std::forward<Rest>(rest)...);
}
模板
无效排序(C&C、Rest和Rest){
如果constexpr(is_list::value==true)c.sort();
else std::sort(c.begin(),c.end());
如果constexpr(sizeof…(rest)>=1)//大小写为空
排序(std::forward(rest)…);
}
否则,您可以使用模板专门化、重载甚至SFINEA
但是我认为重载是使用c++11最简单的方法
//handleing empty case for terminal recursion
void sort() {}
//list case
template<typename T, typename...Rest>
void sort(std::list<T>& c, Rest&& ... rest){
c.sort();
sort(std::forward<Rest>(rest)...);
}
//forward list case
template<typename T, typename...Rest>
void sort(std::forward_list<T>& c, Rest&& ... rest){
c.sort();
sort(std::forward<Rest>(rest)...);
}
//other containers case
template<typename C, typename...Rest>
void sort(C&& c, Rest&& ... rest) {
std::sort(c.begin(), c.end());
sort(std::forward<Rest>(rest)...);
}
//为终端递归处理空案例
void sort(){}
//列表案例
样板
无效排序(标准::列表和c、剩余和剩余){
c、 排序();
排序(std::forward(rest)…);
}
//转发列表案例
样板
无效排序(标准::转发列表和c、剩余和剩余){
c、 排序();
排序(std::forward(rest)…);
}
//其他货柜箱
样板
无效排序(C&&C,Rest&&…Rest){
排序(c.begin(),c.end());
排序(std::forward(rest)…);
}
一旦解决了您看到的问题,您的代码就有了另一个问题
您没有处理递归的终端情况
我还添加了完美的转发
如果您使用的是c++17,如果愿意,可以使用constexpr
template<typename C, typename...Rest>
void sort(C &c, Rest&& ... rest){
if constexpr (is_list<C>::value == true) c.sort();
else std::sort(c.begin(), c.end());
if constexpr (sizeof...(rest) >= 1) // empty case
sort(std::forward<Rest>(rest)...);
}
模板
无效排序(C&C、Rest和Rest){
如果constexpr(is_list::value==true)c.sort();
else std::sort(c.begin(),c.end());
如果constexpr(sizeof…(rest)>=1)//大小写为空
排序(std::forward(rest)…);
}
否则,您可以使用模板专门化、重载甚至SFINEA
但是我认为重载是使用c++11最简单的方法
//handleing empty case for terminal recursion
void sort() {}
//list case
template<typename T, typename...Rest>
void sort(std::list<T>& c, Rest&& ... rest){
c.sort();
sort(std::forward<Rest>(rest)...);
}
//forward list case
template<typename T, typename...Rest>
void sort(std::forward_list<T>& c, Rest&& ... rest){
c.sort();
sort(std::forward<Rest>(rest)...);
}
//other containers case
template<typename C, typename...Rest>
void sort(C&& c, Rest&& ... rest) {
std::sort(c.begin(), c.end());
sort(std::forward<Rest>(rest)...);
}
//为终端递归处理空案例
void sort(){}
//列表案例
样板
无效排序(标准::列表和c、剩余和剩余){
c、 排序();
排序(std::forward(rest)…);
}
//转发列表案例
样板
无效排序(标准::转发列表和c、剩余和剩余){
c、 排序();
排序(std::forward(rest)…);
}
//其他货柜箱
样板
无效排序(C&&C,Rest&&…Rest){
排序(c.begin(),c.end());
排序(std::forward(rest)…);
}
在C++17或更高版本中查找if constexpr
。否则,您需要针对不同的容器类型显式地专门使用sort()
函数,而不是尝试执行运行时测试。在C++17或更高版本中查找if constexpr
。否则,您需要为不同的容器类型显式地专门化sort()
函数,而不是尝试进行运行时测试。是的,我就是这样解决的,但您的代码似乎有一个小问题:第二种排序应该是:template::type*=nullptr>
,否则它对ListWare来说将是不明确的,void*
不是正确的非类型模板参数。你真的应该坚持下去。@YSC今天学到了一些新东西。你知道它的原因以及编译器从不抱怨的原因吗?@YSC找到了它@Tartarus啊,对了,我的错,我在这个问题上有点太快了。是的,我就是这样解决的,但你的代码似乎有点小问题:第二类应该是:template::type*=nullptr>
,否则它对ListWare来说会很模糊,void*
不是正确的非类型模板参数。你真的应该坚持下去。@YSC今天学到了一些新东西。你知道它的原因和为什么编译器从不抱怨吗?@YSC得到了它@Tartarus啊,对了,我的错,我在这方面有点太快了。