internal.hpp
Go to the documentation of this file.
1 
14 #ifndef CORE_INTERNAL_HPP
15 #define CORE_INTERNAL_HPP
16 
17 /* This is a header containing common implementation specific code, to
18  * reduce the complexity of the other headers, especially those that are
19  * closely intertwined, such as <core/functional.hpp> and <core/type_traits.hpp>
20  *
21  * Additionally, some of this code is duplicated elsewhere (such as class_of,
22  * and meta::identity), but aliases are placed to lessen any impact that this
23  * might have.
24  */
25 
26 #include <type_traits>
27 #include <functional>
28 #include <utility>
29 #include <ciso646>
30 
31 #include "meta.hpp"
32 
33 namespace core {
34 inline namespace v2 {
35 namespace impl {
36 
37 template <class T, class Void, template <class...> class, class...>
38 struct make_detect : meta::identity<T> { using value_t = ::std::false_type; };
39 template <class T, template <class...> class U, class... Args>
40 struct make_detect<T, meta::deduce<U<Args...>>, U, Args...> :
41  meta::identity<U<Args...>>
42 { using value_t = ::std::true_type; };
43 
44 /* extremely useful custom type traits */
45 template <class T> struct class_of : meta::identity<T> { };
46 template <class Signature, class T>
47 struct class_of<Signature T::*> : meta::identity<T> { };
48 
49 /* aliases */
50 template <class T> using class_of_t = typename class_of<T>::type;
51 template <class T> using decay_t = typename ::std::decay<T>::type;
52 template <class T>
53 using remove_reference_t = typename ::std::remove_reference<T>::type;
54 template <bool B, class T = void>
55 using enable_if_t = typename ::std::enable_if<B, T>::type;
56 
57 /* is_nothrow_swappable plumbing */
58 using ::std::declval;
60 
61 // MSVC 2015 workaround
62 template <class T, class U>
64  template <class X, class Y>
65  static auto test (void*) noexcept(true) -> decltype(
66  swap(declval<X&>(), declval<Y&>())
67  );
68 
69  template <class, class>
70  static void test (...) noexcept(false);
71 
72  static constexpr bool value = noexcept(test<T, U>(nullptr));
73 };
74 
75 // MSVC 2015 workaround
76 template <class T, class U>
78  template <
79  class X,
80  class Y,
81  bool B=noexcept(swap(declval<X&>(), declval<Y&>()))
82  > static void test (enable_if_t<B>*) noexcept(true);
83 
84  template <class, class>
85  static void test (...) noexcept(false);
86 
87  static constexpr bool value = noexcept(test<T, U>(nullptr));
88 };
89 
90 template <class, class, class=void>
91 struct is_swappable : ::std::false_type { };
92 
93 template <class T, class U>
94 struct is_swappable<
95  T,
96  U,
97  meta::deduce<
98  is_swappable_with<T, U>,
99  is_swappable_with<U, T>
100  >
101 > : ::std::true_type { };
102 
103 template <class T, class U=T>
105  is_swappable<T, U>::value,
106  is_noexcept_swappable_with<T, U>::value,
107  is_noexcept_swappable_with<U, T>::value
108 > { };
109 
110 /*
111  * If I can't amuse myself when working with C++ templates, then life isn't
112  * worth living. Bury me with my chevrons.
113  */
114 template <class T>
115 constexpr T&& pass (remove_reference_t<T>& t) noexcept {
116  return static_cast<T&&>(t);
117 }
118 
119 template <class T>
120 constexpr T&& pass (remove_reference_t<T>&& t) noexcept {
121  return static_cast<T&&>(t);
122 }
123 
124 /* INVOKE pseudo-expression plumbing, *much* more simplified than previous
125  * versions of Core
126  */
127 struct undefined { constexpr undefined (...) noexcept { } };
128 
129 /* We get some weird warnings under clang, so we actually give these functions
130  * a body to get rid of it.
131  */
132 template <class... Args>
133 constexpr undefined INVOKE (undefined, Args&&...) noexcept {
134  return undefined { };
135 }
136 
137 template <class Functor, class... Args>
138 constexpr auto INVOKE (Functor&& f, Args&&... args) -> enable_if_t<
139  not ::std::is_member_pointer<decay_t<Functor>>::value,
140  decltype(pass<Functor>(f)(pass<Args>(args)...))
141 > { return pass<Functor>(f)(pass<Args>(args)...); }
142 
143 template <class Functor, class... Args>
144 auto INVOKE (Functor&& f, Args&&... args) -> enable_if_t<
145  ::std::is_member_pointer<decay_t<Functor>>::value,
146  decltype(::std::mem_fn(pass<Functor>(f))(pass<Args>(args)...))
147 > { return ::std::mem_fn(pass<Functor>(f))(pass<Args>(args)...); }
148 
149 template <bool, class...> struct invoke_of { };
150 template <class... Args> struct invoke_of<true, Args...> :
151  meta::identity<decltype(INVOKE(declval<Args>()...))>
152 { };
153 
154 }}} /* namespace core::v2::impl */
155 
156 #endif /* CORE_INTERNAL_HPP */
Copyright © 2013 - 2015 MNMLSTC.
Definition: algorithm.hpp:23
constexpr undefined(...) noexcept
Definition: internal.hpp:127
typename ::std::enable_if< B, T >::type enable_if_t
Definition: internal.hpp:55
typename class_of< T >::type class_of_t
Definition: internal.hpp:50
typename ::std::decay< T >::type decay_t
Definition: internal.hpp:51
constexpr undefined INVOKE(undefined, Args &&...) noexcept
Definition: internal.hpp:133
void swap(any &lhs, any &rhs) noexcept
Definition: any.hpp:333
typename deducer< Ts... >::type deduce
Definition: meta.hpp:38
::std::false_type value_t
Definition: internal.hpp:38
typename ::std::remove_reference< T >::type remove_reference_t
Definition: internal.hpp:53
constexpr T && pass(remove_reference_t< T > &t) noexcept
Definition: internal.hpp:115