c++26新功能—constexpr在稳定排序中的应用
一、constexpr的应用
在前面的标准分析中介绍过,const的应用中的一些限制引出了constexpr。但constexpr的应用也不是一下子全面铺开的。从标准的发展来看,它是一个逐渐渗透的过程。当然这种应用也不是某一方面的简单应用而是在不断的完善和修改过程中,渐渐的推进相关的应用。
应用比较多的主要有:
- 大量的算法开始应用
- 容器中也开始广泛应用
- 标准提供了std::is_constant_evaluated()用来检测调用是否在constexpr上下文中使用
二、稳定排序
在STL中,排序算法是一个重要的应用场景,而且排序本身对效率的应用就很敏感。在实际的排序中,大家可能经常会遇到下面的序列“1,2,2,2,99,3,3,22,11,11,33”,即有不少的相同的数据,如果在排序的过程中,对其相同数据的相对位置保持不变,则就会减少不少的数据交换过程,如果有中间的临时数据,还可以节省不少的临时对象的拷贝处理。在STL中,把这种排序的算法叫做稳定排序(Stable Sorting)。
在C++26中,对稳定排序中的std::stable_sort、std::stable_partition、std::inplace_merge可以应用到constexpr表达式。当然,它们使用执行策略的重载版本不在其内。
看下面的简单模拟应用代码:
template<class Iter, class OutIter>
constexpr void merge_sort(Iter first,
Iter last,
OutIter out)
{
const auto dist{std::distance(first, last)};
if(dist < 2) return;
const auto partition{std::next(first, dist / 2)};
merge_sort(first, partition, out);
merge_sort(partition, last, std::next(out, dist / 2));
std::merge(first, partition, partition, last, out);
std::copy(out, std::next(out, dist), first);
}template<class Iter>
constexpr void merge_sort(Iter first, Iter last)
{
using T = typename Iter::value_type;
std::vector<T> v(first, last);
merge_sort(first, last, v.begin());
}
上面的代码其实就是在std::vetor中,在归并排序利用constexpr实现高效稳定的排序的例子。
但需要说明的是,constexpr的应用还是在逐渐推进过程中,并不是所有的稳定排序都可以使用,那么为什么无法在所有的稳定排序中使用常量表达式呢?一个主要原因就是“排序时需要根据是否有额外存储可用而进行动态分支”。C++26前的版本中,动态分支的路径是无法应用在常量表达式中的。
三、标准应用的趋势
从标准的推进来看,标准还是尽量统一相关的认知,减少特殊的应用。这次将稳定排序增加到常量表达式的应用中,就是这么一种趋势。虽然对标准库来说,本次的完善只是一次单纯的constexpr表达式的扩展应用。但从这一点也可以看出来,标准还是在坚定向前推进。
四、总结
标准的发展没有大家想象的那么快,但只要开了头,坚持不断的向前走,那么一定会越来越完善。只要整体的应用环境不发生重大的革命性变化(比如AI编程获取革命性的进步),那么C++的优势仍然会保持甚至会得到更多的发展。