CreateHasStaticMemberVariable.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 `static constexpr`
15  * variable, optionally also checking its type.
16  *
17  * To generate the corresponding `_v` metafunction, call
18  * `CREATE_HAS_STATIC_MEMBER_VARIABLE` first and then
19  * `CREATE_HAS_STATIC_MEMBER_VARIABLE_V`.
20  *
21  * \example
22  * \snippet Test_CreateHasStaticMemberVariable.cpp CREATE_HAS_EXAMPLE
23  *
24  * \see `CREATE_IS_CALLABLE`
25  */
26 // Use `NoSuchType*****` to represent any `VariableType`, i.e. not checking the
27 // variable type at all. If someone has that many pointers to a thing that isn't
28 // useful, it's their fault...
29 #define CREATE_HAS_STATIC_MEMBER_VARIABLE(CONSTEXPR_NAME) \
30  template <typename CheckingType, typename VariableType = NoSuchType*****, \
31  typename = cpp17::void_t<>> \
32  struct has_##CONSTEXPR_NAME : std::false_type {}; \
33  \
34  template <typename CheckingType, typename VariableType> \
35  struct has_##CONSTEXPR_NAME<CheckingType, VariableType, \
36  cpp17::void_t<std::remove_const_t<decltype( \
37  CheckingType::CONSTEXPR_NAME)>>> \
38  : cpp17::bool_constant< \
39  cpp17::is_same_v<VariableType, NoSuchType*****> or \
40  cpp17::is_same_v< \
41  std::remove_const_t<decltype(CheckingType::CONSTEXPR_NAME)>, \
42  VariableType>> {};
43 
44 // Separate macros to avoid compiler warnings about unused variables
45 #define CREATE_HAS_STATIC_MEMBER_VARIABLE_V(CONSTEXPR_NAME) \
46  template <typename CheckingType, typename VariableType = NoSuchType*****> \
47  static constexpr const bool has_##CONSTEXPR_NAME##_v = \
48  has_##CONSTEXPR_NAME<CheckingType, VariableType>::value;
49 // @}