SUNphi  1.0
SFINAE.hpp
Go to the documentation of this file.
1 #ifndef _SFINAE_HPP
2 #define _SFINAE_HPP
3 
4 /// \file SFINAE.hpp
5 ///
6 /// \brief Defines macros to enable or disable template instantiation
7 ///
8 /// http://en.cppreference.com/w/cpp/language/sfinae
9 
10 #include <metaprogramming/TypeTraits.hpp>
11 
12 namespace SUNphi
13 {
14  /// Provides a SFINAE to be used in template par list
15  ///
16  /// This follows
17  /// https://stackoverflow.com/questions/32636275/sfinae-with-variadic-templates
18  /// as in this example
19  /// \code
20  /// template <typename D,
21  /// SFINAE_ON_TEMPLATE_ARG(IsSame<D,int>)>
22  /// void foo(D i) {} // fails if D is not int
23  /// \endcode
24 #define SFINAE_ON_TEMPLATE_ARG(...)
25  TypeIf<(__VA_ARGS__),void*> =nullptr
26 
27  /// Provides template par list to unprioritize default SFINAE
28  ///
29  /// Use as last argument of a function overloaded by a other
30  /// implementations using SFINAE to detect the proper version to be
31  /// used. This has to be used in conjunction with the other macros
32  /// SFINAE_WORSEN_DEFAULT_VERSION_ARGS and
33  /// SFINAE_WORSEN_DEFAULT_VERSION_ARGS_CHECK as in this example
34  ///
35  /// \code
36  /// template <typename T,
37  /// SFINAE_WORSEN_DEFAULT_VERSION_TEMPLATE_PARS>
38  /// int tell(T a,SFINAE_WORSEN_DEFAULT_VERSION_ARGS)
39  /// {
40  /// SFINAE_WORSEN_DEFAULT_VERSION_ARGS_CHECK;
41  /// return 1;
42  /// }
43  ///
44  /// template <typename T,
45  /// std::enable_if_t<sizeof(T)==4,void*> =nullptr>
46  /// decltype(auto) tell(T&& a)
47  /// {
48  /// return a+1;
49  /// }
50  ///
51  /// int main()
52  /// {
53  /// tell(1); //returns 2
54  ///
55  /// return 0;
56  /// }
57  ///\endcode
58 #define SFINAE_WORSEN_DEFAULT_VERSION_TEMPLATE_PARS
59  typename...DummyTypes /* Fake list of types */
60 
61  /// Provide empty list of args, used to unprioritize default version
62 #define SFINAE_WORSEN_DEFAULT_VERSION_ARGS
63  DummyTypes... /*< Fake list of args */
64 
65  /// Check that no extra arg is passed
66 #define SFINAE_WORSEN_DEFAULT_VERSION_ARGS_CHECK
67  STATIC_ASSERT_ARE_N_TYPES(0,DummyTypes)
68 
69  //////////////////////////////////////////////////////////////////////
70 
71  /// SFINAE for template class specialisation
72  ///
73  /// Mechanism to allow the usage of SFINAE to allow a class specialization.
74  /// Follows the advice of https://stackoverflow.com/a/30991097 to
75  /// create a class providing the type itself
76  ///
77  /// Example:
78  ///
79  /// \code
80  ///
81  /// Class which needs to be explicitly specialized with SFINAE
82  /// template <typename T>
83  /// class SpecializableClass
84  /// {
85  /// };
86  ///
87  /// /// Dummy type to be used to specialize the class
88  /// class SpecializingArg
89  /// {
90  /// };
91  ///
92  /// PROVIDE_ENABLE_IF_FOR_TYPE(SpecializingArg);
93  ///
94  /// /// Specializes the class SpecializableClass
95  /// SFINAE_TEMPLATE_CLASS_SPECIALIZATION_PREAMBLE
96  /// class SpecializableClass<SFINAE_TEMPLATE_CLASS_SPECIALIZATION_ARG(SpecializingArg)>
97  /// {
98  /// SFINAE_TEMPLATE_CLASS_SPECIALIZATION_PROVIDE_TYPE;
99  ///
100  /// /// To show explicit usage of T
101  /// SpecializableClass<T>()
102  /// {
103  /// }
104  /// };
105  ///
106  /// \endcode
107  ///
108 #define SFINAE_TEMPLATE_CLASS_SPECIALIZATION_PREAMBLE
109  template <template<typename...> typename TT,
110  typename...Ts>
111 
112  /// To be used as an argument of the specialization
113 #define SFINAE_TEMPLATE_CLASS_SPECIALIZATION_ARG(TYPE)
114  EnableIfIs ## TYPE<TT<Ts...>,TT<Ts...>>
115 
116  /// Provides the type inside the specialized class
117 #define SFINAE_TEMPLATE_CLASS_SPECIALIZATION_PROVIDE_TYPE
118  /*! Type used as an argument of the template specialization */
119  using T=
120  TT<Ts...>
121 }
122 
123 #endif
#define STATIC_ASSERT_ARE_N_TYPES(N, UNEXP_PARPACK)
Static assert if not passing exactly N types.
Definition: TypeTraits.hpp:422