`<xutility>`: concept failed constraint has poor diagnostics.
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 11.1k
- Forks
- 1.7k
- Avg merge
- 4d 15h
- Merged PRs (30d)
- 22
Description
For the following code:
https://godbolt.org/z/vYcqsW5qx
#include <algorithm>
#include <iterator>
#include <ranges>
struct it {
it() noexcept;
it &operator++() noexcept;
it operator++(int) noexcept;
int *operator*() const noexcept;
int *operator->() const noexcept;
bool operator==(const it &it) const noexcept;
bool operator!=(const it &it) const noexcept;
};
template <typename T>
struct adapter {
it begin() const;
it end() const;
};
template <class T>
constexpr bool std::ranges::enable_borrowed_range<adapter<T>> = true;
using collection = adapter<int>;
bool pred(int *pdod) noexcept;
template <typename Col, typename Pred>
bool any_of_wrapper(Col &&col, Pred pred) {
return std::any_of(col.begin(), col.end(), pred);
}
void cpp17() { std::begin(collection()); }
void cpp20() { std::ranges::begin(collection()); }
MSVC does not emit concepts diagnostics, so this bug report focuses on clang.
Using the Microsoft STL I see:
a.cpp(26,16): warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
void cpp17() { std::begin(collection()); }
^~~~~~~~~~ ~~~~~~~~~~~~
a.cpp(27,16): error: no matching function for call to object of type 'const _Begin::_Cpo'
void cpp20() { std::ranges::begin(collection()); }
^~~~~~~~~~~~~~~~~~
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.31.31103\include\xutility(2023,39): note: candidate template ignored: constraints not satisfied
[with _Ty = adapter<int>]
_NODISCARD constexpr auto operator()(_Ty&& _Val) const noexcept(_Choice<_Ty&>._No_throw) {
^
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.31.31103\include\xutility(2022,27): note: because '_Choice<adapter<int> &>._Strategy != _St::_None'
evaluated to false
requires (_Choice<_Ty&>._Strategy != _St::_None)
^
1 warning and 1 error generated.
The way the Microsoft STL is written the diagnostic is not useful. I have to look at the code and even then it does not tell me what the issue is.
If use the GCC STL I see:
<source>:34:16: error: no matching function for call to object of type 'const __cust_access::_Begin'
void cpp20() { std::ranges::begin(collection()); }
^~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.1/../../../../include/c++/12.0.1/bits/ranges_base.h:114:2: note: candidate template ignored: constraints not satisfied [with _Tp = adapter<int>]
operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.1/../../../../include/c++/12.0.1/bits/ranges_base.h:111:11: note: because 'is_array_v<remove_reference_t<adapter<int> > >' evaluated to false
requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.1/../../../../include/c++/12.0.1/bits/ranges_base.h:111:50: note: and 'adapter<int>' does not satisfy '__member_begin'
requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.1/../../../../include/c++/12.0.1/bits/iterator_concepts.h:947:6: note: because 'decay_t<it>' (aka 'it') does not satisfy 'input_or_output_iterator':
{ __decay_copy(__t.begin()) } -> input_or_output_iterator;
^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.1/../../../../include/c++/12.0.1/bits/iterator_concepts.h:616:5: note: because 'it' does not satisfy 'weakly_incrementable'
&& weakly_incrementable<_Iter>;
^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.1/../../../../include/c++/12.0.1/bits/iterator_concepts.h:207:7: note: because 'typename iter_difference_t<_Iter>' would be invalid: no type named 'difference_type' in 'std::incrementable_traits<it>'
using __iter_diff_t = typename
^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.1/../../../../include/c++/12.0.1/bits/ranges_base.h:112:7: note: and 'adapter<int>' does not satisfy '__adl_begin'
|| __adl_begin<_Tp>
^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.1/../../../../include/c++/12.0.1/bits/iterator_concepts.h:958:19: note: because '__decay_copy(begin(__t))' would be invalid: call to deleted function 'begin'
{ __decay_copy(begin(__t)) } -> input_or_output_iterator;
^
1 error generated.
Which gives me a clear pointer of what failed.
Would it be possible to refactor the code in xutility related to ranges::begin constraints so that the compiler is able to emit proper constraints diagnostics?
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
The issue points to ranges::begin constraints in xutility; start there and compare the reported MSVC and GCC diagnostics. Refactor that area so a failing iterator constraint is surfaced directly in clang diagnostics, then verify the example reports the missing requirement rather than only a failed aggregate constraint.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- developer-experience
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100