Overloader.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <utility>
7 
9 
10 #if defined(__clang__) || __GNUC__ > 5
11 #define OVERLOADER_CONSTEXPR \
12  constexpr
13 #else
14 #define OVERLOADER_CONSTEXPR
15 #endif
16 
17 namespace overloader_detail {
18 struct no_such_type;
19 } // namespace overloader_detail
20 
21 /*!
22  * \ingroup UtilitiesGroup
23  * \brief Used for overloading lambdas, useful for lambda-SFINAE
24  *
25  * \snippet Utilities/Test_Overloader.cpp overloader_example
26  */
27 template <class... Fs>
28 class Overloader;
29 
30 template <class F1, class F2, class F3, class F4, class F5, class F6, class F7,
31  class F8, class... Fs>
32 class Overloader<F1, F2, F3, F4, F5, F6, F7, F8, Fs...>
33  : F1, F2, F3, F4, F5, F6, F7, F8, Overloader<Fs...> {
34  public:
35  OVERLOADER_CONSTEXPR Overloader(F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6,
36  F7 f7, F8 f8, Fs... fs)
37  : F1(std::move(f1)),
38  F2(std::move(f2)),
39  F3(std::move(f3)),
40  F4(std::move(f4)),
41  F5(std::move(f5)),
42  F6(std::move(f6)),
43  F7(std::move(f7)),
44  F8(std::move(f8)),
45  Overloader<Fs...>(std::move(fs)...) {}
46 
47  using F1::operator();
48  using F2::operator();
49  using F3::operator();
50  using F4::operator();
51  using F5::operator();
52  using F6::operator();
53  using F7::operator();
54  using F8::operator();
56 };
57 
58 template <class F1, class F2, class F3, class F4, class... Fs>
59 class Overloader<F1, F2, F3, F4, Fs...> : F1, F2, F3, F4, Overloader<Fs...> {
60  public:
61  OVERLOADER_CONSTEXPR Overloader(F1 f1, F2 f2, F3 f3, F4 f4, Fs... fs)
62  : F1(std::move(f1)),
63  F2(std::move(f2)),
64  F3(std::move(f3)),
65  F4(std::move(f4)),
66  Overloader<Fs...>(std::move(fs)...) {}
67 
68  using F1::operator();
69  using F2::operator();
70  using F3::operator();
71  using F4::operator();
73 };
74 
75 template <class F1, class F2, class... Fs>
76 class Overloader<F1, F2, Fs...> : F1, F2, Overloader<Fs...> {
77  public:
78  OVERLOADER_CONSTEXPR Overloader(F1 f1, F2 f2, Fs... fs)
79  : F1(std::move(f1)),
80  F2(std::move(f2)),
81  Overloader<Fs...>(std::move(fs)...) {}
82 
83  using F1::operator();
84  using F2::operator();
86 };
87 
88 template <class F>
89 class Overloader<F> : F {
90  public:
91  explicit OVERLOADER_CONSTEXPR Overloader(F f) : F(std::move(f)) {}
92 
93  using F::operator();
94 };
95 
96 template <>
97 class Overloader<> {
98  public:
99  using type = Overloader;
100  SPECTRE_ALWAYS_INLINE void operator()(
101  const overloader_detail::no_such_type& /*unused*/) noexcept {}
102 };
103 
104 /*!
105  * \ingroup UtilitiesGroup
106  * \brief Create `Overloader<Fs...>`, see Overloader for details
107  */
108 template <class... Fs>
109 OVERLOADER_CONSTEXPR Overloader<Fs...> make_overloader(Fs... fs) {
110  return Overloader<Fs...>{std::move(fs)...};
111 }
Overloader< Fs... > make_overloader(Fs... fs)
Create Overloader<Fs...>, see Overloader for details.
Definition: Overloader.hpp:109
Used for overloading lambdas, useful for lambda-SFINAE.
Definition: Overloader.hpp:28
#define SPECTRE_ALWAYS_INLINE
Always inline a function. Only use this if you benchmarked the code.
Definition: ForceInline.hpp:20
Definition: Overloader.hpp:17
Defines macro to always inline a function.