Skip to content

Commit 8ec4ce6

Browse files
committed
Lots of C++11 / C++14 template magic added to:
* <functional> - reference_wrapper, invoke * <memory> - addressof * <utility> - forward, move * <tuple> - make_tuple * <type_traits> - too many to list
1 parent d394950 commit 8ec4ce6

File tree

8 files changed

+479
-208
lines changed

8 files changed

+479
-208
lines changed

bits/pair.hpp

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#pragma once
2+
3+
#include "rel_ops.hpp"
4+
5+
namespace std {
6+
7+
template <class T1, class T2> struct _UCXXEXPORT pair {
8+
typedef T1 first_type;
9+
typedef T2 second_type;
10+
11+
T1 first;
12+
T2 second;
13+
pair() : first(), second() { }
14+
pair(const T1& x, const T2& y) : first(x), second(y) { }
15+
template<class U, class V> pair(const pair<U, V> &p) : first(p.first), second(p.second) { }
16+
};
17+
18+
template <class T1, class T2> bool operator==(const pair<T1,T2>& x, const pair<T1,T2>& y){
19+
using namespace rel_ops;
20+
return (x.first == y.first && x.second==y.second);
21+
}
22+
template <class T1, class T2> bool operator< (const pair<T1,T2>& x, const pair<T1,T2>& y){
23+
return x.first < y.first || (!(y.first < x.first) && x.second < y.second);
24+
}
25+
template <class T1, class T2> bool operator!=(const pair<T1,T2>& x, const pair<T1,T2>& y){
26+
return !(x == y);
27+
}
28+
template <class T1, class T2> bool operator> (const pair<T1,T2>& x, const pair<T1,T2>& y){
29+
return y < x;
30+
}
31+
template <class T1, class T2> bool operator>=(const pair<T1,T2>& x, const pair<T1,T2>& y){
32+
return !(x < y);
33+
}
34+
template <class T1, class T2> bool operator<=(const pair<T1,T2>& x, const pair<T1,T2>& y){
35+
return !(y < x);
36+
}
37+
template <class T1, class T2> pair<T1,T2> make_pair(const T1& x, const T2& y){
38+
return pair<T1,T2>(x, y);
39+
}
40+
41+
}

bits/rel_ops.hpp

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#pragma once
2+
3+
namespace std {
4+
5+
namespace rel_ops {
6+
template<class T> inline bool operator!=(const T& x, const T& y){
7+
return !(x == y);
8+
}
9+
10+
template<class T> inline bool operator> (const T& x, const T& y){
11+
return ( y < x);
12+
}
13+
14+
template<class T> inline bool operator<=(const T& x, const T& y){
15+
return !( y < x );
16+
}
17+
18+
template<class T> inline bool operator>=(const T& x, const T& y){
19+
return !(x < y);
20+
}
21+
}
22+
23+
}

bits/type_traits_impl.hpp

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#pragma once
2+
3+
namespace std {
4+
5+
/// void_t
6+
template< class... >
7+
using void_t = void;
8+
9+
10+
/// Integral constant
11+
template <class T, T v>
12+
struct integral_constant
13+
{
14+
static constexpr T value = v;
15+
typedef T value_type;
16+
typedef integral_constant type; // using injected-class-name
17+
constexpr operator value_type() const noexcept { return value; }
18+
constexpr value_type operator()() const noexcept { return value; } //since c++14
19+
};
20+
21+
template <bool B>
22+
using bool_constant = integral_constant<bool, B>;
23+
24+
/// typedef for true_type
25+
typedef bool_constant<true> true_type;
26+
27+
/// typedef for false_type
28+
typedef bool_constant<false> false_type;
29+
30+
/// is_lvalue_reference
31+
template <typename>
32+
struct is_lvalue_reference : public false_type
33+
{
34+
};
35+
36+
template <typename _Tp>
37+
struct is_lvalue_reference<_Tp &> : public true_type
38+
{
39+
};
40+
41+
/// is_rvalue_reference
42+
template <typename>
43+
struct is_rvalue_reference : public false_type
44+
{
45+
};
46+
47+
template <typename _Tp>
48+
struct is_rvalue_reference<_Tp &&> : public true_type
49+
{
50+
};
51+
52+
}

functional

+73
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#define __STD_HEADER_FUNCTIONAL 1
2121

2222
#include <basic_definitions>
23+
#include <memory>
24+
#include <type_traits>
2325

2426
#pragma GCC visibility push(default)
2527

@@ -431,6 +433,77 @@ compose2(const Op1 & fn1, const Op2 & fn2, const Op3 & fn3){
431433
return binary_compose<Op1, Op2, Op3>(fn1, fn2, fn3);
432434
}
433435

436+
/// Invoke
437+
438+
namespace detail {
439+
template <class T>
440+
struct is_reference_wrapper : std::false_type {};
441+
template <class U>
442+
struct is_reference_wrapper<std::reference_wrapper<U>> : std::true_type {};
443+
444+
template <class T, class Type, class T1, class... Args>
445+
decltype(auto) INVOKE(Type T::* f, T1&& t1, Args&&... args)
446+
{
447+
if (std::is_member_function_pointer<decltype(f)>::value) {
448+
if (std::is_base_of<T, std::decay_t<T1>>::value)
449+
return (std::forward<T1>(t1).*f)(std::forward<Args>(args)...);
450+
else if (is_reference_wrapper<std::decay_t<T1>>::value)
451+
return (t1.get().*f)(std::forward<Args>(args)...);
452+
else
453+
return ((*std::forward<T1>(t1)).*f)(std::forward<Args>(args)...);
454+
} else {
455+
static_assert(std::is_member_function_pointer<decltype(f)>::value, "std::is_member_function_pointer<decltype(f)>::value");
456+
static_assert(sizeof...(args) == 0, "(sizeof...(args) == 0");
457+
if (std::is_base_of<T, std::decay_t<T1>>::value)
458+
return std::forward<T1>(t1).*f;
459+
else if (is_reference_wrapper<std::decay_t<T1>>::value)
460+
return t1.get().*f;
461+
else
462+
return (*std::forward<T1>(t1)).*f;
463+
}
464+
}
465+
466+
template <class F, class... Args>
467+
decltype(auto) INVOKE(F&& f, Args&&... args)
468+
{
469+
return std::forward<F>(f)(std::forward<Args>(args)...);
470+
}
471+
} // namespace detail
472+
473+
template< class F, class... Args>
474+
std::invoke_result_t<F, Args...> invoke(F&& f, Args&&... args)
475+
{
476+
return detail::INVOKE(std::forward<F>(f), std::forward<Args>(args)...);
477+
}
478+
479+
template <class T>
480+
class reference_wrapper {
481+
public:
482+
// types
483+
typedef T type;
484+
485+
// construct/copy/destroy
486+
reference_wrapper(T& ref) noexcept : _ptr(std::addressof(ref)) {}
487+
reference_wrapper(T&&) = delete;
488+
reference_wrapper(const reference_wrapper&) noexcept = default;
489+
490+
// assignment
491+
reference_wrapper& operator=(const reference_wrapper& x) noexcept = default;
492+
493+
// access
494+
operator T& () const noexcept { return *_ptr; }
495+
T& get() const noexcept { return *_ptr; }
496+
497+
template< class... ArgTypes >
498+
std::invoke_result_t<T&, ArgTypes...>
499+
operator() ( ArgTypes&&... args ) const {
500+
return invoke(get(), std::forward<ArgTypes>(args)...);
501+
}
502+
503+
private:
504+
T* _ptr;
505+
};
506+
434507
#pragma GCC visibility pop
435508

436509
#endif

memory

+10-1
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,25 @@
2121
#include <cstddef>
2222
#include <cstdlib>
2323
#include <iterator_base>
24-
#include <utility>
2524
#include <cstdio>
2625

26+
#include <bits/pair.hpp> // std::pair
27+
2728
#ifndef HEADER_STD_MEMORY
2829
#define HEADER_STD_MEMORY 1
2930

3031
#pragma GCC visibility push(default)
3132

3233
namespace std{
3334

35+
template< class T >
36+
T* addressof(T& arg) noexcept
37+
{
38+
return reinterpret_cast<T*>(
39+
&const_cast<char&>(
40+
reinterpret_cast<const volatile char&>(arg)));
41+
}
42+
3443
template <class T> class allocator;
3544
// Specialize for void:
3645

tuple

+52-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
#pragma once
22

3+
#include <functional>
4+
#include <type_traits>
5+
#include <utility>
6+
37
namespace std
48
{
59

@@ -42,10 +46,57 @@ namespace detail {
4246
};
4347
}
4448

45-
template <int index, typename First, typename... Rest>
49+
template <size_t index, typename First, typename... Rest>
4650
auto get(const tuple<First, Rest...> &t) -> decltype(detail::tuple_getter<index, First, Rest...>::value(&t))
4751
{
4852
return detail::tuple_getter<index, First, Rest...>::value(&t);
4953
}
5054

55+
template< class T >
56+
class tuple_size; /*undefined*/
57+
58+
template< class... Types >
59+
class tuple_size< std::tuple<Types...> >
60+
: public std::integral_constant<std::size_t, sizeof...(Types)> { };
61+
62+
template< class T >
63+
class tuple_size<const T>
64+
: public std::integral_constant<std::size_t, tuple_size<T>::value> { };
65+
66+
template< class T >
67+
class tuple_size< volatile T >
68+
: public std::integral_constant<std::size_t, tuple_size<T>::value> { };
69+
70+
template< class T >
71+
class tuple_size< const volatile T >
72+
: public std::integral_constant<std::size_t, tuple_size<T>::value> { };
73+
74+
#if __cplusplus >= 201703L // c++17
75+
template< class T >
76+
inline constexpr size_t tuple_size_v = tuple_size<T>::value;
77+
#endif
78+
79+
namespace detail {
80+
template <class T>
81+
struct unwrap_refwrapper
82+
{
83+
using type = T;
84+
};
85+
86+
template <class T>
87+
struct unwrap_refwrapper<reference_wrapper<T>>
88+
{
89+
using type = T&;
90+
};
91+
92+
template <class T>
93+
using special_decay_t = typename unwrap_refwrapper<typename std::decay<T>::type>::type;
94+
}
95+
96+
template <typename... Types>
97+
auto make_tuple(Types&&... args)
98+
{
99+
return std::tuple<detail::special_decay_t<Types>...>(std::forward<Types>(args)...);
100+
}
101+
51102
}

0 commit comments

Comments
 (0)