c++ - 为什么 clang 认为 gcc 的 subrange 不满足 gcc 的 __ranges_begin 函数概念要求?
问题描述
clang 失败的代码(虽然 gcc 看起来不错)
int arr[] { 111, 222, 333};
ranges::subrange(
ranges::begin(arr),ranges::end(arr) );
看起来clang声称gcc的子范围没有开始功能?!
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/11.0.0/../../../../include/c++/11.0.0/bits/iterator_concepts.h:953:35: note: and 'std::ranges::subrange<int *, int *, std::ranges::subrange_kind::sized> &' does not satisfy '__member_begin'
requires is_array_v<_Tp> || __member_begin<_Tp&> || __adl_begin<_Tp&>
^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/11.0.0/../../../../include/c++/11.0.0/bits/iterator_concepts.h:937:33: note: because '__detail::__decay_copy(__t.begin())' would be invalid: no member named 'begin' in 'std::ranges::subrange<int *, int *, std::ranges::subrange_kind::sized>'
{ __detail::__decay_copy(__t.begin()) } -> input_or_output_iterator;
^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/11.0.0/../../../../include/c++/11.0.0/bits/iterator_concepts.h:953:59: note: and 'std::ranges::subrange<int *, int *, std::ranges::subrange_kind::sized> &' does not satisfy '__adl_begin'
requires is_array_v<_Tp> || __member_begin<_Tp&> || __adl_begin<_Tp&>
[直播]
gcc 的iterator_concepts.h的一部分:
namespace __detail
{
template<typename _Tp>
constexpr decay_t<_Tp>
__decay_copy(_Tp&& __t)
noexcept(is_nothrow_convertible_v<_Tp, decay_t<_Tp>>)
{ return std::forward<_Tp>(__t); }
template<typename _Tp>
concept __member_begin = requires(_Tp& __t)
{
{ __detail::__decay_copy(__t.begin()) } -> input_or_output_iterator;
};
void begin(auto&) = delete;
void begin(const auto&) = delete;
template<typename _Tp>
concept __adl_begin = __class_or_enum<remove_reference_t<_Tp>>
&& requires(_Tp& __t)
{
{ __detail::__decay_copy(begin(__t)) } -> input_or_output_iterator;
};
// Simplified version of std::ranges::begin that only supports lvalues,
// for use by __range_iter_t below.
template<typename _Tp>
requires is_array_v<_Tp> || __member_begin<_Tp&> || __adl_begin<_Tp&>
auto
__ranges_begin(_Tp& __t)
{
if constexpr (is_array_v<_Tp>)
{
static_assert(sizeof(remove_all_extents_t<_Tp>) != 0,
"not array of incomplete type");
return __t + 0;
}
else if constexpr (__member_begin<_Tp&>)
return __t.begin();
else
return begin(__t);
}
// Implementation of std::ranges::iterator_t, without using ranges::begin.
template<typename _Tp>
using __range_iter_t
= decltype(__detail::__ranges_begin(std::declval<_Tp&>()));
} // namespace __detail
解决方案
推荐阅读
- javascript - 数组中日期的最小值/最大值
- node.js - 无法让 VSCode 调试与我的 NodeJs 应用程序一起使用
- javascript - 如果我选择其他 React Router 会改变状态?
- android - 如何每秒刷新一次视图
- excel - Excel - 批量删除相同的单词和不同括号内容的其余部分
- c# - 使用“禁止”列表禁止列表中的变量
- emacs - Emacs 函数崩溃
- apache-spark - 不可序列化的结果:使用 Spark / Scala 读取序列文件时的 org.apache.hadoop.io.IntWritable
- r - 防止在ggplot2中居中多层标题
- linux - 对 mkfifo 的并发写入似乎丢失了