blob: 829fa497bf8e2848f0e7c96c9dc349bbcc818ce8 (
plain)
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
|
#pragma once
// #################################################################################################
// A unique type generator
template <typename T, typename TAG, typename specialization = void>
class Unique
{
private:
T val; // no default initialization so that std::is_trivial_v<Unique<T>> == true
public:
using type = T;
~Unique() = default;
constexpr explicit Unique(T b_)
: val{ b_ }
{
}
// rule of 5
constexpr Unique() = default;
constexpr Unique(Unique const&) = default;
constexpr Unique(Unique&&) = default;
constexpr Unique& operator=(Unique const&) = default;
constexpr Unique& operator=(Unique&&) = default;
// can't implicitly affect from base type
Unique& operator=(T const&) = delete;
constexpr Unique& operator=(T&&) = delete;
// cast
constexpr operator T() const noexcept { return val; }
// pre-increment
auto& operator++() noexcept
{
++val;
return *this;
}
// post-increment
auto operator++(int) noexcept
{
return Unique<T, TAG>{ std::exchange(val, val + 1) };
}
};
template <typename T, typename TAG>
class Unique<T, TAG, std::enable_if_t<!std::is_scalar_v<T>>>
: public T
{
public:
using type = T;
using T::T;
explicit Unique(T const& b_)
: T{ b_ }
{
}
};
#define DECLARE_UNIQUE_TYPE(_name, _type) using _name = Unique<_type, class Unique_##_name##_Tag>
|