Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,10 @@
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<iterator_traits_cpp17_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<iterator_traits_cpp17_proxy_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<iterator_traits_cpp17_input_iterator>);
static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<iterator_traits_cpp17_proxy_input_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<iterator_traits_cpp17_proxy_input_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<iterator_traits_cpp17_forward_iterator>);
static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<iterator_traits_cpp17_bidirectional_iterator>);
static_assert(
std::__iterator_traits_detail::__cpp17_random_access_iterator<iterator_traits_cpp17_random_access_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<iterator_traits_cpp17_bidirectional_iterator>);
static_assert(std::__iterator_traits_detail::__cpp17_random_access_iterator<iterator_traits_cpp17_random_access_iterator>);

static_assert(std::__iterator_traits_detail::__cpp17_random_access_iterator<int*>);
static_assert(std::__iterator_traits_detail::__cpp17_random_access_iterator<int const*>);
Expand All @@ -52,8 +49,7 @@ static_assert(std::__iterator_traits_detail::__cpp17_random_access_iterator<int
static_assert(std::__iterator_traits_detail::__cpp17_random_access_iterator<std::array<int, 10>::iterator>);
static_assert(std::__iterator_traits_detail::__cpp17_random_access_iterator<std::array<int, 10>::const_iterator>);
static_assert(std::__iterator_traits_detail::__cpp17_random_access_iterator<std::array<int, 10>::reverse_iterator>);
static_assert(
std::__iterator_traits_detail::__cpp17_random_access_iterator<std::array<int, 10>::const_reverse_iterator>);
static_assert(std::__iterator_traits_detail::__cpp17_random_access_iterator<std::array<int, 10>::const_reverse_iterator>);

// <deque>
static_assert(std::__iterator_traits_detail::__cpp17_random_access_iterator<std::deque<int>::iterator>);
Expand All @@ -64,22 +60,18 @@ static_assert(std::__iterator_traits_detail::__cpp17_random_access_iterator<std:
// <filesystem>
#ifndef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::filesystem::directory_iterator>);
static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::filesystem::recursive_directory_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::filesystem::recursive_directory_iterator>);
#endif

// <forward_list>
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::forward_list<int>::iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::forward_list<int>::const_iterator>);

// <iterator>
static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::back_insert_iterator<std::vector<int> > >);
static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::front_insert_iterator<std::vector<int> > >);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::insert_iterator<std::vector<int> > >);
static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::move_iterator<std::vector<int>::iterator> >);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::back_insert_iterator<std::vector<int>>>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::front_insert_iterator<std::vector<int>>>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::insert_iterator<std::vector<int>>>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::move_iterator<int*>>);

// <list>
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::list<int>::iterator>);
Expand All @@ -91,15 +83,12 @@ static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::map<int, int>::iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::map<int, int>::const_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::map<int, int>::reverse_iterator>);
static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::map<int, int>::const_reverse_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::map<int, int>::const_reverse_iterator>);

static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::multimap<int, int>::iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::multimap<int, int>::const_iterator>);
static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::multimap<int, int>::reverse_iterator>);
static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::multimap<int, int>::const_reverse_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::multimap<int, int>::reverse_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::multimap<int, int>::const_reverse_iterator>);

// <set>
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::set<int>::iterator>);
Expand All @@ -110,8 +99,7 @@ static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::multiset<int>::iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::multiset<int>::const_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::multiset<int>::reverse_iterator>);
static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::multiset<int>::const_reverse_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::multiset<int>::const_reverse_iterator>);

// <string>
static_assert(std::__iterator_traits_detail::__cpp17_random_access_iterator<std::string::iterator>);
Expand All @@ -127,36 +115,25 @@ static_assert(std::__iterator_traits_detail::__cpp17_random_access_iterator<std:

// <unordered_map>
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_map<int, int>::iterator>);
static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_map<int, int>::const_iterator>);
static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_map<int, int>::local_iterator>);
static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_map<int, int>::const_local_iterator>);

static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_multimap<int, int>::iterator>);
static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_multimap<int, int>::const_iterator>);
static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_multimap<int, int>::local_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<
std::unordered_multimap<int, int>::const_local_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_map<int, int>::const_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_map<int, int>::local_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_map<int, int>::const_local_iterator>);

static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_multimap<int, int>::iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_multimap<int, int>::const_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_multimap<int, int>::local_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_multimap<int, int>::const_local_iterator>);

// <unordered_set>
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_set<int>::iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_set<int>::const_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_set<int>::local_iterator>);
static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_set<int>::const_local_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_set<int>::const_local_iterator>);

static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_multiset<int>::iterator>);
static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_multiset<int>::const_iterator>);
static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_multiset<int>::local_iterator>);
static_assert(
!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_multiset<int>::const_local_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_multiset<int>::const_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_multiset<int>::local_iterator>);
static_assert(!std::__iterator_traits_detail::__cpp17_random_access_iterator<std::unordered_multiset<int>::const_local_iterator>);

// <vector>
static_assert(std::__iterator_traits_detail::__cpp17_random_access_iterator<std::vector<int>::iterator>);
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

#include "test_macros.h"

// clang-format off
template <class T>
concept check_has_difference_type = requires {
typename std::incrementable_traits<T>::difference_type;
Expand All @@ -29,10 +28,9 @@ template <class T, class Expected>
concept check_difference_type_matches =
check_has_difference_type<T> &&
std::same_as<typename std::incrementable_traits<T>::difference_type, Expected>;
// clang-format on

template <class T, class Expected>
[[nodiscard]] constexpr bool check_incrementable_traits() noexcept {
constexpr bool check_incrementable_traits() {
constexpr bool result = check_difference_type_matches<T, Expected>;
static_assert(check_difference_type_matches<T const, Expected> == result);
return result;
Expand All @@ -41,8 +39,7 @@ template <class T, class Expected>
static_assert(check_incrementable_traits<float*, std::ptrdiff_t>());
static_assert(check_incrementable_traits<float const*, std::ptrdiff_t>());
static_assert(check_incrementable_traits<float volatile*, std::ptrdiff_t>());
static_assert(
check_incrementable_traits<float const volatile*, std::ptrdiff_t>());
static_assert(check_incrementable_traits<float const volatile*, std::ptrdiff_t>());
static_assert(check_incrementable_traits<float**, std::ptrdiff_t>());

static_assert(check_incrementable_traits<int[], std::ptrdiff_t>());
Expand Down Expand Up @@ -83,42 +80,31 @@ struct non_integral_difference_type {
static_assert(check_incrementable_traits<non_integral_difference_type, void>());

struct int_subtraction {
friend int operator-(int_subtraction, int_subtraction) noexcept;
friend int operator-(int_subtraction, int_subtraction);
};
static_assert(check_incrementable_traits<int_subtraction, int>());
static_assert(!check_incrementable_traits<int_subtraction volatile&, int>());
static_assert(
!check_incrementable_traits<int_subtraction const volatile&, int>());
static_assert(!check_incrementable_traits<int_subtraction const volatile&, int>());

struct char_subtraction {
friend char operator-(char_subtraction, char_subtraction) noexcept;
friend char operator-(char_subtraction, char_subtraction);
};
static_assert(check_incrementable_traits<char_subtraction, signed char>());

struct unsigned_int_subtraction_with_cv {
friend unsigned int
operator-(unsigned_int_subtraction_with_cv const&,
unsigned_int_subtraction_with_cv const&) noexcept;
friend unsigned int
operator-(unsigned_int_subtraction_with_cv const volatile&,
unsigned_int_subtraction_with_cv const volatile&) noexcept;
friend unsigned int operator-(unsigned_int_subtraction_with_cv const&, unsigned_int_subtraction_with_cv const&);
friend unsigned int operator-(unsigned_int_subtraction_with_cv const volatile&, unsigned_int_subtraction_with_cv const volatile&);
};
static_assert(
check_incrementable_traits<unsigned_int_subtraction_with_cv, int>());
static_assert(check_incrementable_traits<
unsigned_int_subtraction_with_cv volatile&, int>());
static_assert(check_incrementable_traits<
unsigned_int_subtraction_with_cv const volatile&, int>());
static_assert(check_incrementable_traits<unsigned_int_subtraction_with_cv, int>());
static_assert(check_incrementable_traits<unsigned_int_subtraction_with_cv volatile&, int>());
static_assert(check_incrementable_traits<unsigned_int_subtraction_with_cv const volatile&, int>());

struct specialised_incrementable_traits {};
namespace std {
template <>
struct incrementable_traits<specialised_incrementable_traits> {
struct std::incrementable_traits<specialised_incrementable_traits> {
using difference_type = int;
};
} // namespace std
static_assert(
check_incrementable_traits<specialised_incrementable_traits, int>());
static_assert(check_incrementable_traits<specialised_incrementable_traits, int>());

static_assert(!check_has_difference_type<void>);
static_assert(!check_has_difference_type<float>);
Expand All @@ -136,17 +122,13 @@ static_assert(!check_has_difference_type<int (*)() noexcept>);
static_assert(!check_has_difference_type<int (&)()>);
static_assert(!check_has_difference_type<int (&)() noexcept>);

#define TEST_POINTER_TO_MEMBER_FUNCTION(type, cv_qualifier) \
static_assert(!check_has_difference_type<int (type::*)() cv_qualifier>); \
static_assert( \
!check_has_difference_type<int (type::*)() cv_qualifier noexcept>); \
static_assert(!check_has_difference_type<int (type::*)() cv_qualifier&>); \
static_assert( \
!check_has_difference_type<int (type::*)() cv_qualifier & noexcept>); \
static_assert(!check_has_difference_type<int (type::*)() cv_qualifier&&>); \
static_assert(!check_has_difference_type < int (type::*)() \
cv_qualifier&& noexcept >); \
/**/
#define TEST_POINTER_TO_MEMBER_FUNCTION(type, cv) \
static_assert(!check_has_difference_type<int (type::*)() cv>); \
static_assert(!check_has_difference_type<int (type::*)() cv noexcept>); \
static_assert(!check_has_difference_type<int (type::*)() cv&>); \
static_assert(!check_has_difference_type<int (type::*)() cv& noexcept>); \
static_assert(!check_has_difference_type<int (type::*)() cv&&>); \
static_assert(!check_has_difference_type<int (type::*)() cv&& noexcept>);

struct empty {};

Expand All @@ -157,104 +139,102 @@ TEST_POINTER_TO_MEMBER_FUNCTION(empty, volatile);
TEST_POINTER_TO_MEMBER_FUNCTION(empty, const volatile);

struct void_subtraction {
friend void operator-(void_subtraction, void_subtraction) noexcept;
friend void operator-(void_subtraction, void_subtraction);
};
static_assert(!check_has_difference_type<void_subtraction>);

#define TEST_NOT_DIFFERENCE_TYPE(qual1, qual2) \
struct TEST_CONCAT(test_subtraction_, __LINE__) { \
friend int operator-(TEST_CONCAT(test_subtraction_, __LINE__) qual1, \
TEST_CONCAT(test_subtraction_, __LINE__) qual2); \
}; \
static_assert(!check_has_difference_type<TEST_CONCAT(test_subtraction_, \
__LINE__)>) /**/

TEST_NOT_DIFFERENCE_TYPE(&, &);
TEST_NOT_DIFFERENCE_TYPE(&, const&);
TEST_NOT_DIFFERENCE_TYPE(&, volatile&);
TEST_NOT_DIFFERENCE_TYPE(&, const volatile&);
TEST_NOT_DIFFERENCE_TYPE(&, &&);
TEST_NOT_DIFFERENCE_TYPE(&, const&&);
TEST_NOT_DIFFERENCE_TYPE(&, volatile&&);
TEST_NOT_DIFFERENCE_TYPE(&, const volatile&&);

TEST_NOT_DIFFERENCE_TYPE(const&, &);
// TEST_NOT_DIFFERENCE_TYPE(const&, const&); // == true
TEST_NOT_DIFFERENCE_TYPE(const&, volatile&);
// TEST_NOT_DIFFERENCE_TYPE(const&, const volatile&); // invalid
TEST_NOT_DIFFERENCE_TYPE(const&, &&);
TEST_NOT_DIFFERENCE_TYPE(const&, const&&);
TEST_NOT_DIFFERENCE_TYPE(const&, volatile&&);
TEST_NOT_DIFFERENCE_TYPE(const&, const volatile&&);

TEST_NOT_DIFFERENCE_TYPE(volatile&, &);
TEST_NOT_DIFFERENCE_TYPE(volatile&, const&);
TEST_NOT_DIFFERENCE_TYPE(volatile&, volatile&);
TEST_NOT_DIFFERENCE_TYPE(volatile&, const volatile&);
TEST_NOT_DIFFERENCE_TYPE(volatile&, &&);
TEST_NOT_DIFFERENCE_TYPE(volatile&, const&&);
TEST_NOT_DIFFERENCE_TYPE(volatile&, volatile&&);
TEST_NOT_DIFFERENCE_TYPE(volatile&, const volatile&&);

TEST_NOT_DIFFERENCE_TYPE(const volatile&, &);
// TEST_NOT_DIFFERENCE_TYPE(const volatile&, const&); // invalid
TEST_NOT_DIFFERENCE_TYPE(const volatile&, volatile&);
// TEST_NOT_DIFFERENCE_TYPE(const volatile&, const volatile&); // invalid
TEST_NOT_DIFFERENCE_TYPE(const volatile&, &&);
TEST_NOT_DIFFERENCE_TYPE(const volatile&, const&&);
TEST_NOT_DIFFERENCE_TYPE(const volatile&, volatile&&);
TEST_NOT_DIFFERENCE_TYPE(const volatile&, const volatile&&);

TEST_NOT_DIFFERENCE_TYPE(&&, &);
TEST_NOT_DIFFERENCE_TYPE(&&, const&);
TEST_NOT_DIFFERENCE_TYPE(&&, volatile&);
TEST_NOT_DIFFERENCE_TYPE(&&, const volatile&);
TEST_NOT_DIFFERENCE_TYPE(&&, &&);
TEST_NOT_DIFFERENCE_TYPE(&&, const&&);
TEST_NOT_DIFFERENCE_TYPE(&&, volatile&&);
TEST_NOT_DIFFERENCE_TYPE(&&, const volatile&&);

TEST_NOT_DIFFERENCE_TYPE(const&&, &);
TEST_NOT_DIFFERENCE_TYPE(const&&, const&);
TEST_NOT_DIFFERENCE_TYPE(const&&, volatile&);
TEST_NOT_DIFFERENCE_TYPE(const&&, const volatile&);
TEST_NOT_DIFFERENCE_TYPE(const&&, &&);
TEST_NOT_DIFFERENCE_TYPE(const&&, const&&);
TEST_NOT_DIFFERENCE_TYPE(const&&, volatile&&);
TEST_NOT_DIFFERENCE_TYPE(const&&, const volatile&&);

TEST_NOT_DIFFERENCE_TYPE(volatile&&, &);
TEST_NOT_DIFFERENCE_TYPE(volatile&&, const&);
TEST_NOT_DIFFERENCE_TYPE(volatile&&, volatile&);
TEST_NOT_DIFFERENCE_TYPE(volatile&&, const volatile&);
TEST_NOT_DIFFERENCE_TYPE(volatile&&, &&);
TEST_NOT_DIFFERENCE_TYPE(volatile&&, const&&);
TEST_NOT_DIFFERENCE_TYPE(volatile&&, volatile&&);
TEST_NOT_DIFFERENCE_TYPE(volatile&&, const volatile&&);

TEST_NOT_DIFFERENCE_TYPE(const volatile&&, &);
TEST_NOT_DIFFERENCE_TYPE(const volatile&&, const&);
TEST_NOT_DIFFERENCE_TYPE(const volatile&&, volatile&);
TEST_NOT_DIFFERENCE_TYPE(const volatile&&, const volatile&);
TEST_NOT_DIFFERENCE_TYPE(const volatile&&, &&);
TEST_NOT_DIFFERENCE_TYPE(const volatile&&, const&&);
TEST_NOT_DIFFERENCE_TYPE(const volatile&&, volatile&&);
TEST_NOT_DIFFERENCE_TYPE(const volatile&&, const volatile&&);

TEST_NOT_DIFFERENCE_TYPE(&, NO_QUALIFIER);
// TEST_NOT_DIFFERENCE_TYPE(const&, NO_QUALIFIER); // == true
TEST_NOT_DIFFERENCE_TYPE(volatile&, NO_QUALIFIER);
// TEST_NOT_DIFFERENCE_TYPE(const volatile&, NO_QUALIFIER); // invalid
TEST_NOT_DIFFERENCE_TYPE(&&, NO_QUALIFIER);
TEST_NOT_DIFFERENCE_TYPE(const&&, NO_QUALIFIER);
TEST_NOT_DIFFERENCE_TYPE(volatile&&, NO_QUALIFIER);
TEST_NOT_DIFFERENCE_TYPE(const volatile&&, NO_QUALIFIER);

TEST_NOT_DIFFERENCE_TYPE(NO_QUALIFIER, &);
// TEST_NOT_DIFFERENCE_TYPE(NO_QUALIFIER, const&); // == true
TEST_NOT_DIFFERENCE_TYPE(NO_QUALIFIER, volatile&);
// TEST_NOT_DIFFERENCE_TYPE(NO_QUALIFIER, const volatile&); // invalid
TEST_NOT_DIFFERENCE_TYPE(NO_QUALIFIER, &&);
TEST_NOT_DIFFERENCE_TYPE(NO_QUALIFIER, const&&);
TEST_NOT_DIFFERENCE_TYPE(NO_QUALIFIER, volatile&&);
TEST_NOT_DIFFERENCE_TYPE(NO_QUALIFIER, const volatile&&);
#define TEST_NOT_DIFFERENCE_TYPE(S, qual1, qual2) \
struct S { \
friend int operator-(S qual1, S qual2); \
}; \
static_assert(!check_has_difference_type<S>)

TEST_NOT_DIFFERENCE_TYPE(A01, &, &);
TEST_NOT_DIFFERENCE_TYPE(A02, &, const&);
TEST_NOT_DIFFERENCE_TYPE(A03, &, volatile&);
TEST_NOT_DIFFERENCE_TYPE(A04, &, const volatile&);
TEST_NOT_DIFFERENCE_TYPE(A05, &, &&);
TEST_NOT_DIFFERENCE_TYPE(A06, &, const&&);
TEST_NOT_DIFFERENCE_TYPE(A07, &, volatile&&);
TEST_NOT_DIFFERENCE_TYPE(A08, &, const volatile&&);

TEST_NOT_DIFFERENCE_TYPE(A11, const&, &);
// TEST_NOT_DIFFERENCE_TYPE(A12, const&, const&); // == true
TEST_NOT_DIFFERENCE_TYPE(A13, const&, volatile&);
// TEST_NOT_DIFFERENCE_TYPE(A14, const&, const volatile&); // invalid
TEST_NOT_DIFFERENCE_TYPE(A15, const&, &&);
TEST_NOT_DIFFERENCE_TYPE(A16, const&, const&&);
TEST_NOT_DIFFERENCE_TYPE(A17, const&, volatile&&);
TEST_NOT_DIFFERENCE_TYPE(A18, const&, const volatile&&);

TEST_NOT_DIFFERENCE_TYPE(A21, volatile&, &);
TEST_NOT_DIFFERENCE_TYPE(A22, volatile&, const&);
TEST_NOT_DIFFERENCE_TYPE(A23, volatile&, volatile&);
TEST_NOT_DIFFERENCE_TYPE(A24, volatile&, const volatile&);
TEST_NOT_DIFFERENCE_TYPE(A25, volatile&, &&);
TEST_NOT_DIFFERENCE_TYPE(A26, volatile&, const&&);
TEST_NOT_DIFFERENCE_TYPE(A27, volatile&, volatile&&);
TEST_NOT_DIFFERENCE_TYPE(A28, volatile&, const volatile&&);

TEST_NOT_DIFFERENCE_TYPE(A31, const volatile&, &);
// TEST_NOT_DIFFERENCE_TYPE(A32, const volatile&, const&); // invalid
TEST_NOT_DIFFERENCE_TYPE(A33, const volatile&, volatile&);
// TEST_NOT_DIFFERENCE_TYPE(A34, const volatile&, const volatile&); // invalid
TEST_NOT_DIFFERENCE_TYPE(A35, const volatile&, &&);
TEST_NOT_DIFFERENCE_TYPE(A36, const volatile&, const&&);
TEST_NOT_DIFFERENCE_TYPE(A37, const volatile&, volatile&&);
TEST_NOT_DIFFERENCE_TYPE(A38, const volatile&, const volatile&&);

TEST_NOT_DIFFERENCE_TYPE(A41, &&, &);
TEST_NOT_DIFFERENCE_TYPE(A42, &&, const&);
TEST_NOT_DIFFERENCE_TYPE(A43, &&, volatile&);
TEST_NOT_DIFFERENCE_TYPE(A44, &&, const volatile&);
TEST_NOT_DIFFERENCE_TYPE(A45, &&, &&);
TEST_NOT_DIFFERENCE_TYPE(A46, &&, const&&);
TEST_NOT_DIFFERENCE_TYPE(A47, &&, volatile&&);
TEST_NOT_DIFFERENCE_TYPE(A48, &&, const volatile&&);

TEST_NOT_DIFFERENCE_TYPE(A51, const&&, &);
TEST_NOT_DIFFERENCE_TYPE(A52, const&&, const&);
TEST_NOT_DIFFERENCE_TYPE(A53, const&&, volatile&);
TEST_NOT_DIFFERENCE_TYPE(A54, const&&, const volatile&);
TEST_NOT_DIFFERENCE_TYPE(A55, const&&, &&);
TEST_NOT_DIFFERENCE_TYPE(A56, const&&, const&&);
TEST_NOT_DIFFERENCE_TYPE(A57, const&&, volatile&&);
TEST_NOT_DIFFERENCE_TYPE(A58, const&&, const volatile&&);

TEST_NOT_DIFFERENCE_TYPE(A61, volatile&&, &);
TEST_NOT_DIFFERENCE_TYPE(A62, volatile&&, const&);
TEST_NOT_DIFFERENCE_TYPE(A63, volatile&&, volatile&);
TEST_NOT_DIFFERENCE_TYPE(A64, volatile&&, const volatile&);
TEST_NOT_DIFFERENCE_TYPE(A65, volatile&&, &&);
TEST_NOT_DIFFERENCE_TYPE(A66, volatile&&, const&&);
TEST_NOT_DIFFERENCE_TYPE(A67, volatile&&, volatile&&);
TEST_NOT_DIFFERENCE_TYPE(A68, volatile&&, const volatile&&);

TEST_NOT_DIFFERENCE_TYPE(A71, const volatile&&, &);
TEST_NOT_DIFFERENCE_TYPE(A72, const volatile&&, const&);
TEST_NOT_DIFFERENCE_TYPE(A73, const volatile&&, volatile&);
TEST_NOT_DIFFERENCE_TYPE(A74, const volatile&&, const volatile&);
TEST_NOT_DIFFERENCE_TYPE(A75, const volatile&&, &&);
TEST_NOT_DIFFERENCE_TYPE(A76, const volatile&&, const&&);
TEST_NOT_DIFFERENCE_TYPE(A77, const volatile&&, volatile&&);
TEST_NOT_DIFFERENCE_TYPE(A78, const volatile&&, const volatile&&);

TEST_NOT_DIFFERENCE_TYPE(A81, &, NO_QUALIFIER);
// TEST_NOT_DIFFERENCE_TYPE(A82, const&, NO_QUALIFIER); // == true
TEST_NOT_DIFFERENCE_TYPE(A83, volatile&, NO_QUALIFIER);
// TEST_NOT_DIFFERENCE_TYPE(A84, const volatile&, NO_QUALIFIER); // invalid
TEST_NOT_DIFFERENCE_TYPE(A85, &&, NO_QUALIFIER);
TEST_NOT_DIFFERENCE_TYPE(A86, const&&, NO_QUALIFIER);
TEST_NOT_DIFFERENCE_TYPE(A87, volatile&&, NO_QUALIFIER);
TEST_NOT_DIFFERENCE_TYPE(A88, const volatile&&, NO_QUALIFIER);

TEST_NOT_DIFFERENCE_TYPE(A91, NO_QUALIFIER, &);
// TEST_NOT_DIFFERENCE_TYPE(A92, NO_QUALIFIER, const&); // == true
TEST_NOT_DIFFERENCE_TYPE(A93, NO_QUALIFIER, volatile&);
// TEST_NOT_DIFFERENCE_TYPE(A94, NO_QUALIFIER, const volatile&); // invalid
TEST_NOT_DIFFERENCE_TYPE(A95, NO_QUALIFIER, &&);
TEST_NOT_DIFFERENCE_TYPE(A96, NO_QUALIFIER, const&&);
TEST_NOT_DIFFERENCE_TYPE(A97, NO_QUALIFIER, volatile&&);
TEST_NOT_DIFFERENCE_TYPE(A98, NO_QUALIFIER, const volatile&&);
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@
#include <concepts>
#include <vector>

template <class T>
constexpr bool has_no_iter_difference_t() {
return !requires { typename std::iter_difference_t<T>; };
}

template <class T, class Expected>
[[nodiscard]] constexpr bool check_iter_difference_t() {
constexpr bool check_iter_difference_t() {
constexpr bool result = std::same_as<std::iter_difference_t<T>, Expected>;
static_assert(std::same_as<std::iter_difference_t<T const>, Expected> == result);
static_assert(std::same_as<std::iter_difference_t<T volatile>, Expected> == result);
Expand All @@ -39,32 +44,17 @@ static_assert(check_iter_difference_t<int*, std::ptrdiff_t>());
static_assert(check_iter_difference_t<std::vector<int>::iterator, std::ptrdiff_t>());

struct int_subtraction {
friend int operator-(int_subtraction, int_subtraction) noexcept;
friend int operator-(int_subtraction, int_subtraction);
};
static_assert(check_iter_difference_t<int_subtraction, int>());

// clang-format off
template <class T>
requires requires { typename std::iter_difference_t<T>; }
[[nodiscard]] constexpr bool check_no_iter_difference_t() {
return false;
}
// clang-format on

template <class T>
[[nodiscard]] constexpr bool check_no_iter_difference_t() {
return true;
}

static_assert(check_no_iter_difference_t<void>());
static_assert(check_no_iter_difference_t<double>());
static_assert(has_no_iter_difference_t<void>());
static_assert(has_no_iter_difference_t<double>());

struct S {};
static_assert(check_no_iter_difference_t<S>());
static_assert(has_no_iter_difference_t<S>());

struct void_subtraction {
friend void operator-(void_subtraction, void_subtraction);
};
static_assert(check_no_iter_difference_t<void_subtraction>());

int main(int, char**) { return 0; }
static_assert(has_no_iter_difference_t<void_subtraction>());
Original file line number Diff line number Diff line change
Expand Up @@ -20,168 +20,133 @@
#include <string>
#include <vector>

// `value_type` and `element_type` member aliases aren't actually used to declare anytihng, so GCC
// thinks they're completely unused.
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"

// clang-format off
template <class T>
concept check_has_value_type = requires {
concept has_no_value_type = !requires {
typename std::indirectly_readable_traits<T>::value_type;
};

template <class T, class Expected>
concept check_value_type_matches =
check_has_value_type<T> &&
concept value_type_matches =
std::same_as<typename std::indirectly_readable_traits<T>::value_type, Expected>;
// clang-format on

template <class T>
constexpr bool check_pointer() {
constexpr bool result = check_value_type_matches<T*, T>;
static_assert(check_value_type_matches<T const*, T> == result);
static_assert(check_value_type_matches<T volatile*, T> == result);
static_assert(check_value_type_matches<T const volatile*, T> == result);
constexpr bool result = value_type_matches<T*, T>;
static_assert(value_type_matches<T const*, T> == result);
static_assert(value_type_matches<T volatile*, T> == result);
static_assert(value_type_matches<T const volatile*, T> == result);

static_assert(check_value_type_matches<T* const, T> == result);
static_assert(check_value_type_matches<T const* const, T> == result);
static_assert(check_value_type_matches<T volatile* const, T> == result);
static_assert(check_value_type_matches<T const volatile* const, T> == result);
static_assert(value_type_matches<T* const, T> == result);
static_assert(value_type_matches<T const* const, T> == result);
static_assert(value_type_matches<T volatile* const, T> == result);
static_assert(value_type_matches<T const volatile* const, T> == result);

return result;
}

static_assert(!check_pointer<void>());
static_assert(check_pointer<int>());
static_assert(check_pointer<long>());
static_assert(check_pointer<double>());
static_assert(check_pointer<double*>());

struct S {};
static_assert(check_pointer<S>());

template <class T>
constexpr bool check_array() {
constexpr bool result = check_value_type_matches<T[], T>;
static_assert(check_value_type_matches<T const[], T> == result);
static_assert(check_value_type_matches<T volatile[], T> == result);
static_assert(check_value_type_matches<T const volatile[], T> == result);
static_assert(check_value_type_matches<T[10], T> == result);
static_assert(check_value_type_matches<T const[10], T> == result);
static_assert(check_value_type_matches<T volatile[10], T> == result);
static_assert(check_value_type_matches<T const volatile[10], T> == result);
return result;
static_assert(value_type_matches<T[], T>);
static_assert(value_type_matches<T const[], T>);
static_assert(value_type_matches<T volatile[], T>);
static_assert(value_type_matches<T const volatile[], T>);
static_assert(value_type_matches<T[10], T>);
static_assert(value_type_matches<T const[10], T>);
static_assert(value_type_matches<T volatile[10], T>);
static_assert(value_type_matches<T const volatile[10], T>);
return true;
}

static_assert(check_array<int>());
static_assert(check_array<long>());
static_assert(check_array<double>());
static_assert(check_array<double*>());
static_assert(check_array<S>());

template <class T, class Expected>
constexpr bool check_explicit_member() {
constexpr bool result = check_value_type_matches<T, Expected>;
static_assert(check_value_type_matches<T const, Expected> == result);
return result;
constexpr bool check_member() {
static_assert(value_type_matches<T, Expected>);
static_assert(value_type_matches<T const, Expected>);
static_assert(value_type_matches<T volatile, Expected>);
return true;
}

struct has_value_type {
using value_type = int;
};
static_assert(check_explicit_member<has_value_type, int>());
static_assert(check_explicit_member<std::vector<int>::iterator, int>());
static_assert(check_pointer<int>());
static_assert(check_pointer<int*>());
static_assert(check_pointer<int[10]>());
static_assert(!check_pointer<void>());
static_assert(!check_pointer<int()>());

struct has_element_type {
using element_type = S;
static_assert(check_array<int>());
static_assert(check_array<int*>());
static_assert(check_array<int[10]>());

template<class T>
struct ValueOf {
using value_type = T;
};
static_assert(check_explicit_member<has_element_type, S>());

struct has_same_value_and_element_type {
using value_type = int;
using element_type = int;
template<class U>
struct ElementOf {
using element_type = U;
};
static_assert(check_explicit_member<has_same_value_and_element_type, int>());
static_assert(check_explicit_member<std::shared_ptr<long>, long>());
static_assert(check_explicit_member<std::shared_ptr<long const>, long>());

// clang-format off
template<class T, class U>
requires std::same_as<std::remove_cv_t<T>, std::remove_cv_t<U> >
struct possibly_different_cv_qualifiers {
struct TwoTypes {
using value_type = T;
using element_type = U;
};
// clang-format on

static_assert(check_explicit_member<possibly_different_cv_qualifiers<int, int>, int>());
static_assert(check_explicit_member<possibly_different_cv_qualifiers<int, int const>, int>());
static_assert(check_explicit_member<possibly_different_cv_qualifiers<int, int volatile>, int>());
static_assert(check_explicit_member<possibly_different_cv_qualifiers<int, int const volatile>, int>());
static_assert(check_explicit_member<possibly_different_cv_qualifiers<int const, int>, int>());
static_assert(check_explicit_member<possibly_different_cv_qualifiers<int const, int const>, int>());
static_assert(check_explicit_member<possibly_different_cv_qualifiers<int const, int volatile>, int>());
static_assert(check_explicit_member<possibly_different_cv_qualifiers<int const, int const volatile>, int>());
static_assert(check_explicit_member<possibly_different_cv_qualifiers<int volatile, int>, int>());
static_assert(check_explicit_member<possibly_different_cv_qualifiers<int volatile, int const>, int>());
static_assert(check_explicit_member<possibly_different_cv_qualifiers<int volatile, int volatile>, int>());
static_assert(check_explicit_member<possibly_different_cv_qualifiers<int volatile, int const volatile>, int>());
static_assert(check_explicit_member<possibly_different_cv_qualifiers<int const volatile, int>, int>());
static_assert(check_explicit_member<possibly_different_cv_qualifiers<int const volatile, int const>, int>());
static_assert(check_explicit_member<possibly_different_cv_qualifiers<int const volatile, int volatile>, int>());
static_assert(check_explicit_member<possibly_different_cv_qualifiers<int const volatile, int const volatile>, int>());

static_assert(check_member<ValueOf<int>, int>());
static_assert(check_member<ValueOf<int[10]>, int[10]>());
static_assert(check_member<ValueOf<int[]>, int[]>());
static_assert(has_no_value_type<ValueOf<void>>);
static_assert(has_no_value_type<ValueOf<int()>>);
static_assert(has_no_value_type<ValueOf<int&>>);
static_assert(has_no_value_type<ValueOf<int&&>>);

static_assert(check_member<ElementOf<int>, int>());
static_assert(check_member<ElementOf<int[10]>, int[10]>());
static_assert(check_member<ElementOf<int[]>, int[]>());
static_assert(has_no_value_type<ElementOf<void>>);
static_assert(has_no_value_type<ElementOf<int()>>);
static_assert(has_no_value_type<ElementOf<int&>>);
static_assert(has_no_value_type<ElementOf<int&&>>);

static_assert(check_member<TwoTypes<int, int>, int>());
static_assert(check_member<TwoTypes<int, int const>, int>());
static_assert(check_member<TwoTypes<int, int volatile>, int>());
static_assert(check_member<TwoTypes<int, int const volatile>, int>());
static_assert(check_member<TwoTypes<int const, int>, int>());
static_assert(check_member<TwoTypes<int const, int const>, int>());
static_assert(check_member<TwoTypes<int const, int volatile>, int>());
static_assert(check_member<TwoTypes<int const, int const volatile>, int>());
static_assert(check_member<TwoTypes<int volatile, int>, int>());
static_assert(check_member<TwoTypes<int volatile, int const>, int>());
static_assert(check_member<TwoTypes<int volatile, int volatile>, int>());
static_assert(check_member<TwoTypes<int volatile, int const volatile>, int>());
static_assert(check_member<TwoTypes<int const volatile, int>, int>());
static_assert(check_member<TwoTypes<int const volatile, int const>, int>());
static_assert(check_member<TwoTypes<int const volatile, int volatile>, int>());
static_assert(check_member<TwoTypes<int const volatile, int const volatile>, int>());
static_assert(has_no_value_type<TwoTypes<int, long>>);
static_assert(has_no_value_type<TwoTypes<int, int&>>);
static_assert(has_no_value_type<TwoTypes<int&, int>>);

struct S2 {};
namespace std {
template <>
struct indirectly_readable_traits<S2> {
struct std::indirectly_readable_traits<S2> {
using value_type = int;
};
} // namespace std
static_assert(check_value_type_matches<S2, int>);
static_assert(check_value_type_matches<std::vector<int>, int>);
static_assert(check_value_type_matches<std::vector<int>::iterator, int>);
static_assert(check_value_type_matches<std::vector<int>::const_iterator, int>);
static_assert(check_value_type_matches<std::istream_iterator<int>, int>);
static_assert(check_value_type_matches<std::istreambuf_iterator<char>, char>);
static_assert(check_value_type_matches<std::optional<int>, int>);

template <class T>
constexpr bool check_ref() {
struct ref_value {
using value_type = T&;
};
constexpr bool result = check_has_value_type<ref_value>;

struct ref_element {
using element_type = T&;
};
static_assert(check_has_value_type<ref_element> == result);

return result;
}

static_assert(!check_ref<int>());
static_assert(!check_ref<S>());
static_assert(!check_ref<std::shared_ptr<long> >());

static_assert(!check_has_value_type<void>);
static_assert(!check_has_value_type<std::nullptr_t>);
static_assert(!check_has_value_type<int>);
static_assert(!check_has_value_type<S>);

struct has_different_value_and_element_type {
using value_type = int;
using element_type = long;
};
static_assert(!check_has_value_type<has_different_value_and_element_type>);

struct void_value {
using value_type = void;
};
static_assert(!check_has_value_type<void_value>);

struct void_element {
using element_type = void;
};
static_assert(!check_has_value_type<void_element>);
static_assert(value_type_matches<S2, int>);
static_assert(value_type_matches<const S2, int>);
static_assert(has_no_value_type<volatile S2>);
static_assert(has_no_value_type<const volatile S2>);
static_assert(has_no_value_type<S2&>);
static_assert(has_no_value_type<const S2&>);

static_assert(check_member<std::vector<int>, int>());
static_assert(check_member<std::vector<int>::iterator, int>());
static_assert(check_member<std::vector<int>::const_iterator, int>());
static_assert(check_member<std::istream_iterator<int>, int>());
static_assert(check_member<std::istreambuf_iterator<char>, char>());
static_assert(check_member<std::optional<int>, int>());
static_assert(check_member<std::shared_ptr<long>, long>());
static_assert(check_member<std::shared_ptr<const long>, long>());
static_assert(has_no_value_type<void>);
static_assert(has_no_value_type<int>);
static_assert(has_no_value_type<std::nullptr_t>);