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 
10 // @{
11 /*!
12  * \ingroup TypeTraitsGroup
13  * \brief Generate a type trait to check if a class has a `static constexpr`
14  * variable, optionally also checking its type.
15  *
16  * To generate the corresponding `_v` metafunction, call
17  * `CREATE_HAS_STATIC_MEMBER_VARIABLE` first and then
18  * `CREATE_HAS_STATIC_MEMBER_VARIABLE_V`.
19  *
20  * \example
21  * \snippet Test_CreateHasStaticMemberVariable.cpp CREATE_HAS_EXAMPLE
22  *
23  * \see `CREATE_IS_CALLABLE`
24  */
25 // Use `NoSuchType*****` to represent any `VariableType`, i.e. not checking the
26 // variable 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_STATIC_MEMBER_VARIABLE(CONSTEXPR_NAME) \
29  template <typename CheckingType, typename VariableType = NoSuchType*****, \
30  typename = std::void_t<>> \
31  struct has_##CONSTEXPR_NAME : std::false_type {}; \
32  \
33  template <typename CheckingType, typename VariableType> \
34  struct has_##CONSTEXPR_NAME<CheckingType, VariableType, \
35  std::void_t<std::remove_const_t<decltype( \
36  CheckingType::CONSTEXPR_NAME)>>> \
37  : std::bool_constant<std::is_same_v<VariableType, NoSuchType*****> or \
38  std::is_same_v<std::remove_const_t<decltype( \
39  CheckingType::CONSTEXPR_NAME)>, \
40  VariableType>> {};
41 
42 // Separate macros to avoid compiler warnings about unused variables
43 #define CREATE_HAS_STATIC_MEMBER_VARIABLE_V(CONSTEXPR_NAME) \
44  template <typename CheckingType, typename VariableType = NoSuchType*****> \
45  static constexpr const bool has_##CONSTEXPR_NAME##_v = \
46  has_##CONSTEXPR_NAME<CheckingType, VariableType>::value;
47 // @}
type_traits