File: internal.hpp

package info (click to toggle)
salmon 1.10.3%2Bds1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 35,148 kB
  • sloc: cpp: 200,707; ansic: 171,082; sh: 859; python: 792; makefile: 238
file content (143 lines) | stat: -rwxr-xr-x 4,246 bytes parent folder | download | duplicates (9)
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 */