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