std::sort并行排序结合自定义迭代器的类型转换与编译报错问题
问题1:保留move运算符的可行方案
可以保留move运算符,只需做两处核心修改即可:
- 补全比较运算符的所有重载组合:当前仅实现了
bool operator<(ref const& a, ref const& b)、bool operator<(ref const& a, val const& b)两类重载,缺少bool operator<(val const& a, ref const& b)的重载。并行STL内部比较时会出现val在前、ref在后的调用场景,找不到对应重载时就会触发类型转换逻辑。 - 为
ref类补充const左值限定的显式val转换重载,和原有右值转换逻辑隔离:
// 原有右值转换,保留move性能优化 operator val() && { return {std::move(*key), std::move(*value)}; } // 新增const左值转换,仅做拷贝不触发move explicit operator val() const& { return {*key, *value}; }
也可以直接给排序接口传入泛型自定义比较器,彻底绕过默认比较器的类型限制:
std::sort(std::execution::par, begin, end, [](const auto& a, const auto& b) { // 直接提取key字段比较,完全避免类型转换 return get_key(a) < get_key(b); });
以上修改不会触发move操作导致的空字符串问题,交换元素时仍会调用右值转换的move逻辑,保留原有的性能优化。
补充问题:编译器尝试类型转换的原因
问题根因为GCC/Clang的并行STL实现与MSVC存在差异:
- GCC/Clang基于TBB的并行STL实现默认使用
std::less<val>作为比较器,该比较器的入参要求为两个const val&类型,传入ref类型参数时,编译器会优先尝试将ref隐式转换为val,而非查找针对ref类型的全局operator<重载。 - 原有实现的
ref::operator val() &&仅支持非const右值ref对象的转换,遇到const左值ref对象时转换失败,就会报出类型转换不合法的错误。 - MSVC的并行STL内部采用泛型比较器实现,会直接匹配到你定义的
ref类型比较重载,因此不会触发类型转换逻辑,编译可正常通过。
内容的提问来源于stack exchange,提问作者Parsort
相关产品推荐
相关产品推荐

