forked from andrewprock/ustl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
typet.h
89 lines (78 loc) · 2.9 KB
/
typet.h
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
// This file is part of the uSTL library, an STL implementation.
//
// Copyright (c) 2007 by Mike Sharov <[email protected]>
//
// This implementation is adapted from the Loki library, distributed under
// the MIT license with Copyright (c) 2001 by Andrei Alexandrescu.
#pragma once
namespace ustl {
/// Template metaprogramming tools
namespace tm {
/// An empty type useful as a placeholder.
class NullType { };
/// Converts an integer to a type.
template <int v> struct Int2Type { enum { value = v }; };
/// Converts an type to a unique empty type.
template <typename T> struct Type2Type { using OriginalType = T; };
/// Selects type Result = flag ? T : U
template <bool flag, typename T, typename U>
struct Select { using Result = T; };
template <typename T, typename U>
struct Select<false, T, U> { using Result = U; };
/// IsSameType<T,U>::value is true when T=U
template <typename T, typename U>
struct IsSameType { enum { value = false }; };
template <typename T>
struct IsSameType<T,T> { enum { value = true }; };
/// \brief Checks for conversion possibilities between T and U
/// Conversion<T,U>::exists is true if T is convertible to U
/// Conversion<T,U>::sameType is true if U is T
template <typename T, typename U>
struct Conversion {
private:
using UT = char;
using TT = short;
static UT Test (U);
static TT Test (...);
static T MakeT (void);
public:
enum {
exists = sizeof(UT) == sizeof(Test(MakeT())),
sameType = false
};
};
template <typename T>
struct Conversion<T, T> { enum { exists = true, sameType = true }; };
template <typename T>
struct Conversion<void, T> { enum { exists = false, sameType = false }; };
template <typename T>
struct Conversion<T, void> { enum { exists = false, sameType = false }; };
template <>
struct Conversion<void, void> { enum { exists = true, sameType = true }; };
/// SuperSubclass<T,U>::value is true when U is derived from T, or when U is T
template <typename T, typename U>
struct SuperSubclass {
enum { value = (::ustl::tm::Conversion<const volatile U*, const volatile T*>::exists &&
!::ustl::tm::Conversion<const volatile T*, const volatile void*>::sameType) };
enum { dontUseWithIncompleteTypes = sizeof(T)==sizeof(U) }; // Dummy enum to make sure that both classes are fully defined.
};
template <>
struct SuperSubclass<void, void> { enum { value = false }; };
template <typename U>
struct SuperSubclass<void, U> {
enum { value = false };
enum { dontUseWithIncompleteTypes = 0==sizeof(U) };
};
template <typename T>
struct SuperSubclass<T, void> {
enum { value = false };
enum { dontUseWithIncompleteTypes = 0==sizeof(T) };
};
/// SuperSubclassStrict<T,U>::value is true when U is derived from T
template <typename T, typename U>
struct SuperSubclassStrict {
enum { value = SuperSubclass<T,U>::value &&
!::ustl::tm::Conversion<const volatile T*, const volatile U*>::sameType };
};
} // namespace tm
} // namespace ustl