Closed
Description
Tested with a recent Clang nightly build, using libc++'s std
module.
template <class _Ip>
using iter_value_t = typename conditional_t<__is_primary_template<iterator_traits<remove_cvref_t<_Ip> > >::value,
indirectly_readable_traits<remove_cvref_t<_Ip> >,
iterator_traits<remove_cvref_t<_Ip> > >::value_type;
Here the indirectly_readable_traits
causes an ambiguous specialization error in the following code:
import std;
template <class It>
class contiguous_iterator {
It it_;
public:
typedef std::contiguous_iterator_tag iterator_category;
typedef typename std::iterator_traits<It>::value_type value_type;
typedef typename std::iterator_traits<It>::difference_type difference_type;
typedef It pointer;
typedef typename std::iterator_traits<It>::reference reference;
typedef typename std::remove_pointer<It>::type element_type;
constexpr It base() const { return it_; }
constexpr contiguous_iterator() : it_() {}
constexpr explicit contiguous_iterator(It it) : it_(it) {}
constexpr reference operator*() const { return *it_; }
constexpr pointer operator->() const { return it_; }
constexpr reference operator[](difference_type n) const { return it_[n]; }
constexpr contiguous_iterator& operator++() {
++it_;
return *this;
}
constexpr contiguous_iterator& operator--() {
--it_;
return *this;
}
constexpr contiguous_iterator operator++(int) { return contiguous_iterator(it_++); }
constexpr contiguous_iterator operator--(int) { return contiguous_iterator(it_--); }
constexpr contiguous_iterator& operator+=(difference_type n) {
it_ += n;
return *this;
}
constexpr contiguous_iterator& operator-=(difference_type n) {
it_ -= n;
return *this;
}
friend constexpr contiguous_iterator operator+(contiguous_iterator x, difference_type n) {
x += n;
return x;
}
friend constexpr contiguous_iterator operator+(difference_type n, contiguous_iterator x) {
x += n;
return x;
}
friend constexpr contiguous_iterator operator-(contiguous_iterator x, difference_type n) {
x -= n;
return x;
}
friend constexpr difference_type operator-(contiguous_iterator x, contiguous_iterator y) { return x.it_ - y.it_; }
friend constexpr bool operator==(const contiguous_iterator& x, const contiguous_iterator& y) {
return x.it_ == y.it_;
}
friend constexpr bool operator!=(const contiguous_iterator& x, const contiguous_iterator& y) {
return x.it_ != y.it_;
}
friend constexpr bool operator<(const contiguous_iterator& x, const contiguous_iterator& y) { return x.it_ < y.it_; }
friend constexpr bool operator<=(const contiguous_iterator& x, const contiguous_iterator& y) {
return x.it_ <= y.it_;
}
friend constexpr bool operator>(const contiguous_iterator& x, const contiguous_iterator& y) { return x.it_ > y.it_; }
friend constexpr bool operator>=(const contiguous_iterator& x, const contiguous_iterator& y) {
return x.it_ >= y.it_;
}
};
using ContiguousIter = contiguous_iterator<const int*>;
// enabling this "fixes" the issue.
//static_assert(std::same_as<std::indirectly_readable_traits<float*>::value_type, float>);
static_assert(std::contiguous_iterator<ContiguousIter>);
This code is reduced from the ranges::data
test. The interesting part is when the indirectly_readable_traits
is used in a static_assert
for an unrelated type, then the code compiles. When using this code without modules it works too.