llvm/libcxx/test/std/iterators/iterator.primitives/iterator.traits/empty.compile.pass.cpp

//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// <iterator>

// struct iterator_traits
// {
// };

#include <iterator>
#include <type_traits>

#include "test_macros.h"

template <class...>
using always_void = void;

#define HAS_XXX(member)                                                                                                \
  template <class T, class = void>                                                                                     \
  struct has_##member : std::false_type {};                                                                            \
  template <class T>                                                                                                   \
  struct has_##member<T, always_void<typename T::member> > : std::true_type {}

HAS_XXX(difference_type);
HAS_XXX(value_type);
HAS_XXX(pointer);
HAS_XXX(reference);
HAS_XXX(iterator_category);

struct A {};
struct NotAnIteratorEmpty {};

struct NotAnIteratorNoDifference {
  //     typedef int                       difference_type;
  typedef A value_type;
  typedef A* pointer;
  typedef A& reference;
  typedef std::forward_iterator_tag iterator_category;
};

struct NotAnIteratorNoValue {
  typedef int difference_type;
  //     typedef A                         value_type;
  typedef A* pointer;
  typedef A& reference;
  typedef std::forward_iterator_tag iterator_category;
};

struct NotAnIteratorNoPointer {
  typedef int difference_type;
  typedef A value_type;
  //     typedef A*                        pointer;
  typedef A& reference;
  typedef std::forward_iterator_tag iterator_category;
};

struct NotAnIteratorNoReference {
  typedef int difference_type;
  typedef A value_type;
  typedef A* pointer;
  //    typedef A&                        reference;
  typedef std::forward_iterator_tag iterator_category;
};

struct NotAnIteratorNoCategory {
  typedef int difference_type;
  typedef A value_type;
  typedef A* pointer;
  typedef A& reference;
  //     typedef std::forward_iterator_tag iterator_category;
};

void test() {
  {
    typedef std::iterator_traits<NotAnIteratorEmpty> T;
    static_assert(!has_difference_type<T>::value, "");
    static_assert(!has_value_type<T>::value, "");
    static_assert(!has_pointer<T>::value, "");
    static_assert(!has_reference<T>::value, "");
    static_assert(!has_iterator_category<T>::value, "");
  }

  {
    typedef std::iterator_traits<NotAnIteratorNoDifference> T;
    static_assert(!has_difference_type<T>::value, "");
    static_assert(!has_value_type<T>::value, "");
    static_assert(!has_pointer<T>::value, "");
    static_assert(!has_reference<T>::value, "");
    static_assert(!has_iterator_category<T>::value, "");
  }

  {
    typedef std::iterator_traits<NotAnIteratorNoValue> T;
    static_assert(!has_difference_type<T>::value, "");
    static_assert(!has_value_type<T>::value, "");
    static_assert(!has_pointer<T>::value, "");
    static_assert(!has_reference<T>::value, "");
    static_assert(!has_iterator_category<T>::value, "");
  }
#if TEST_STD_VER <= 17 || !defined(__cpp_lib_concepts)
  {
    typedef std::iterator_traits<NotAnIteratorNoPointer> T;
    static_assert(!has_difference_type<T>::value, "");
    static_assert(!has_value_type<T>::value, "");
    static_assert(!has_pointer<T>::value, "");
    static_assert(!has_reference<T>::value, "");
    static_assert(!has_iterator_category<T>::value, "");
  }
#endif // TEST_STD_VER <= 17 || !defined(__cpp_lib_concepts)
  {
    typedef std::iterator_traits<NotAnIteratorNoReference> T;
    static_assert(!has_difference_type<T>::value, "");
    static_assert(!has_value_type<T>::value, "");
    static_assert(!has_pointer<T>::value, "");
    static_assert(!has_reference<T>::value, "");
    static_assert(!has_iterator_category<T>::value, "");
  }

  {
    typedef std::iterator_traits<NotAnIteratorNoCategory> T;
    static_assert(!has_difference_type<T>::value, "");
    static_assert(!has_value_type<T>::value, "");
    static_assert(!has_pointer<T>::value, "");
    static_assert(!has_reference<T>::value, "");
    static_assert(!has_iterator_category<T>::value, "");
  }
}