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啊,对了,我的错,我在这方面有点太快了。