Clang 15编译C++20 std::views::filter代码失败的原因及标准库 workaround 咨询
关于Clang 15编译Ranges代码失败的问题解答
代码本身是否存在问题?
这段代码完全符合C++20标准,不存在语法或语义错误。
为什么Clang 15编译失败?
问题出在Clang 15与对应标准库实现的兼容性上:
- 使用libc++时:Clang 15自带的libc并未完整实现C20 Ranges的
std::views命名空间,属于标准库实现滞后,和前端特性支持无关。 - 使用libstdc++时:虽然G12的libstdc已经部分支持Ranges,但Clang 15前端与libstdc++的Ranges实现存在兼容性bug,无法正确解析管道运算符(
|)与std::views::filter返回的部分应用适配器(_Partial对象)的组合操作。
cppreference的编译器支持标注仅针对前端特性支持,并未涵盖标准库实现的完整度,所以会出现标注"完全支持"但实际编译失败的情况。
Clang 16发布前的标准库临时解决方法
不用第三方库的话,有两种稳妥的方式:
- 放弃管道语法,直接调用视图适配器的函数形式
这是最可靠的方法,绕过管道运算符的兼容性问题:#include <ranges> #include <vector> int main() { std::vector x{1,2,3,4}; auto y = std::views::filter(x, [](auto i){ return i < 2; }); } - 针对libstdc++手动补充管道重载(仅限临时应急)
如果你坚持使用管道语法,可以在代码中添加针对_Partial对象的管道运算符重载(仅在Clang 15+libstdc++环境下使用,避免影响其他编译器):
注意:这个重载依赖libstdc++的内部实现细节,未来可能失效,仅作为临时方案。#include <ranges> #include <vector> #include <type_traits> #if defined(__clang__) && (__clang_major__ == 15) && defined(_GLIBCXX_VERSION) namespace std::ranges { template <range R, class F> auto operator|(R&& r, _Partial<views::_Filter, F> const& partial) { return partial.func(std::forward<R>(r), partial.args); } } #endif int main() { std::vector x{1,2,3,4}; auto y = x | std::views::filter([](auto i){ return i <2;}); }
内容的提问来源于stack exchange,提问作者florestan
相关产品推荐
相关产品推荐

