CreateHasTypeAlias.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <type_traits>
7 
8 #include "Utilities/NoSuchType.hpp"
9 #include "Utilities/TypeTraits.hpp"
10 
11 // @{
12 /*!
13  * \ingroup TypeTraitsGroup
14  * \brief Generate a type trait to check if a class has a type alias with a
15  * particular name, optionally also checking its type.
16  *
17  * To generate the corresponding `_v` metafunction, call
18  * `CREATE_HAS_TYPE_ALIAS` first and then `CREATE_HAS_TYPE_ALIAS_V`.
19  *
20  * \example
21  * \snippet Test_CreateHasTypeAlias.cpp CREATE_HAS_TYPE_ALIAS
22  *
23  * \see `CREATE_IS_CALLABLE`
24  */
25 // Use `NoSuchType*****` to represent any `AliasType`, i.e. not checking the
26 // alias type at all. If someone has that many pointers to a thing that isn't
27 // useful, it's their fault...
28 #define CREATE_HAS_TYPE_ALIAS(ALIAS_NAME) \
29  template <typename CheckingType, typename AliasType = NoSuchType*****, \
30  typename = cpp17::void_t<>> \
31  struct has_##ALIAS_NAME : std::false_type {}; \
32  \
33  template <typename CheckingType, typename AliasType> \
34  struct has_##ALIAS_NAME<CheckingType, AliasType, \
35  cpp17::void_t<typename CheckingType::ALIAS_NAME>> \
36  : cpp17::bool_constant< \
37  cpp17::is_same_v<AliasType, NoSuchType*****> or \
38  cpp17::is_same_v<typename CheckingType::ALIAS_NAME, AliasType>> { \
39  };
40 // Separate macros to avoid compiler warnings about unused variables
41 #define CREATE_HAS_TYPE_ALIAS_V(ALIAS_NAME) \
42  template <typename CheckingType, typename AliasType = NoSuchType*****> \
43  static constexpr const bool has_##ALIAS_NAME##_v = \
44  has_##ALIAS_NAME<CheckingType, AliasType>::value;
45 // @}