Skip to content

Commit 84e1f98

Browse files
committed
Rework MovableValue and add MovableLiteral
1 parent 6384bb6 commit 84e1f98

File tree

3 files changed

+261
-23
lines changed

3 files changed

+261
-23
lines changed

include/NazaraUtils/MovableValue.hpp

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,57 @@
77
#ifndef NAZARAUTILS_MOVABLEVALUE_HPP
88
#define NAZARAUTILS_MOVABLEVALUE_HPP
99

10+
#include <type_traits>
11+
1012
namespace Nz
1113
{
14+
template<typename T, T DefaultValue>
15+
class MovableLiteral
16+
{
17+
public:
18+
constexpr MovableLiteral();
19+
template<typename U, typename = std::enable_if_t<std::is_constructible_v<T, U>>> constexpr MovableLiteral(U&& value);
20+
constexpr MovableLiteral(const MovableLiteral&) = default;
21+
constexpr MovableLiteral(MovableLiteral&& val) noexcept;
22+
~MovableLiteral() = default;
23+
24+
constexpr T& Get() &;
25+
constexpr T&& Get() &&;
26+
constexpr const T& Get() const &;
27+
28+
constexpr operator T&() &;
29+
constexpr operator T&&() &&;
30+
constexpr operator const T&() const &;
31+
32+
template<typename U, typename = std::enable_if_t<std::is_assignable_v<T&, U>>> constexpr MovableLiteral& operator=(U&& value);
33+
constexpr MovableLiteral& operator=(const MovableLiteral&) = default;
34+
constexpr MovableLiteral& operator=(MovableLiteral&& ptr) noexcept;
35+
36+
private:
37+
T m_value;
38+
};
39+
1240
template<typename T>
1341
class MovableValue
1442
{
1543
public:
16-
MovableValue(T value = T{});
17-
MovableValue(const MovableValue&) = default;
18-
MovableValue(MovableValue&& ptr) noexcept;
44+
constexpr MovableValue() = default;
45+
template<typename U, typename = std::enable_if_t<std::is_constructible_v<T, U>>> constexpr MovableValue(U&& value);
46+
constexpr MovableValue(const MovableValue&) = default;
47+
constexpr MovableValue(MovableValue&& val) noexcept;
1948
~MovableValue() = default;
2049

21-
T& Get();
22-
const T& Get() const;
50+
constexpr T& Get() &;
51+
constexpr T&& Get() &&;
52+
constexpr const T& Get() const &;
2353

24-
operator T&();
25-
operator const T&() const;
54+
constexpr operator T&() &;
55+
constexpr operator T&&() &&;
56+
constexpr operator const T&() const &;
2657

27-
MovableValue& operator=(T value);
28-
MovableValue& operator=(const MovableValue&) = default;
29-
MovableValue& operator=(MovableValue&& ptr) noexcept;
58+
template<typename U, typename = std::enable_if_t<std::is_assignable_v<T&, U>>> constexpr MovableValue& operator=(U&& value);
59+
constexpr MovableValue& operator=(const MovableValue&) = default;
60+
constexpr MovableValue& operator=(MovableValue&& val) noexcept;
3061

3162
private:
3263
T m_value;

include/NazaraUtils/MovableValue.inl

Lines changed: 98 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,55 +6,140 @@
66

77
namespace Nz
88
{
9+
template<typename T, T DefaultValue>
10+
constexpr MovableLiteral<T, DefaultValue>::MovableLiteral() :
11+
m_value(DefaultValue)
12+
{
13+
}
14+
15+
template<typename T, T DefaultValue>
16+
template<typename U, typename>
17+
constexpr MovableLiteral<T, DefaultValue>::MovableLiteral(U&& value) :
18+
m_value(std::forward<U>(value))
19+
{
20+
}
21+
22+
template<typename T, T DefaultValue>
23+
constexpr MovableLiteral<T, DefaultValue>::MovableLiteral(MovableLiteral&& val) noexcept :
24+
m_value(std::move(val.m_value))
25+
{
26+
val.m_value = DefaultValue;
27+
}
28+
29+
template<typename T, T DefaultValue>
30+
constexpr T& MovableLiteral<T, DefaultValue>::Get() &
31+
{
32+
return m_value;
33+
}
34+
35+
template<typename T, T DefaultValue>
36+
constexpr T&& MovableLiteral<T, DefaultValue>::Get() &&
37+
{
38+
return std::move(m_value);
39+
}
40+
41+
template<typename T, T DefaultValue>
42+
constexpr const T& MovableLiteral<T, DefaultValue>::Get() const &
43+
{
44+
return m_value;
45+
}
46+
47+
template<typename T, T DefaultValue>
48+
constexpr MovableLiteral<T, DefaultValue>::operator T&() &
49+
{
50+
return m_value;
51+
}
52+
53+
template<typename T, T DefaultValue>
54+
constexpr MovableLiteral<T, DefaultValue>::operator T&&() &&
55+
{
56+
return std::move(m_value);
57+
}
58+
59+
template<typename T, T DefaultValue>
60+
constexpr MovableLiteral<T, DefaultValue>::operator const T&() const &
61+
{
62+
return m_value;
63+
}
64+
65+
template<typename T, T DefaultValue>
66+
template<typename U, typename>
67+
constexpr MovableLiteral<T, DefaultValue>& MovableLiteral<T, DefaultValue>::operator=(U&& value)
68+
{
69+
m_value = std::move(value);
70+
return *this;
71+
}
72+
73+
template<typename T, T DefaultValue>
74+
constexpr MovableLiteral<T, DefaultValue>& MovableLiteral<T, DefaultValue>::operator=(MovableLiteral&& val) noexcept
75+
{
76+
std::swap(m_value, val.m_value);
77+
return *this;
78+
}
79+
80+
/************************************************************************/
81+
982
template<typename T>
10-
MovableValue<T>::MovableValue(T value) :
11-
m_value(std::move(value))
83+
template<typename U, typename>
84+
constexpr MovableValue<T>::MovableValue(U&& value) :
85+
m_value(std::forward<U>(value))
1286
{
1387
}
1488

1589
template<typename T>
16-
MovableValue<T>::MovableValue(MovableValue&& val) noexcept :
17-
m_value()
90+
constexpr MovableValue<T>::MovableValue(MovableValue&& val) noexcept :
91+
m_value(std::move(val.m_value))
1892
{
19-
std::swap(m_value, val.m_value);
2093
}
2194

2295
template<typename T>
23-
T& MovableValue<T>::Get()
96+
constexpr T& MovableValue<T>::Get() &
2497
{
2598
return m_value;
2699
}
27100

28101
template<typename T>
29-
const T& MovableValue<T>::Get() const
102+
constexpr T&& MovableValue<T>::Get() &&
103+
{
104+
return std::move(m_value);
105+
}
106+
107+
template<typename T>
108+
constexpr const T& MovableValue<T>::Get() const &
30109
{
31110
return m_value;
32111
}
33112

34113
template<typename T>
35-
MovableValue<T>::operator T&()
114+
constexpr MovableValue<T>::operator T&() &
36115
{
37116
return m_value;
38117
}
39118

40119
template<typename T>
41-
MovableValue<T>::operator const T&() const
120+
constexpr MovableValue<T>::operator T&&() &&
121+
{
122+
return std::move(m_value);
123+
}
124+
125+
template<typename T>
126+
constexpr MovableValue<T>::operator const T&() const &
42127
{
43128
return m_value;
44129
}
45130

46131
template<typename T>
47-
MovableValue<T>& MovableValue<T>::operator=(T value)
132+
template<typename U, typename>
133+
constexpr MovableValue<T>& MovableValue<T>::operator=(U&& value)
48134
{
49135
m_value = std::move(value);
50-
51136
return *this;
52137
}
53138

54139
template<typename T>
55-
MovableValue<T>& MovableValue<T>::operator=(MovableValue&& ptr) noexcept
140+
constexpr MovableValue<T>& MovableValue<T>::operator=(MovableValue&& val) noexcept
56141
{
57-
std::swap(m_value, ptr.m_value);
142+
m_value = std::move(val.m_value);
58143
return *this;
59144
}
60145
}

tests/src/MovableValueTests.cpp

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#include <NazaraUtils/MovableValue.hpp>
2+
#include <CopyCounter.hpp>
3+
#include <catch2/catch_test_macros.hpp>
4+
5+
namespace
6+
{
7+
struct Buffer
8+
{
9+
Buffer() = default;
10+
Buffer(int index) : bufferIndex(index) {}
11+
Buffer(const Buffer&) = default;
12+
Buffer(Buffer&&) noexcept = default;
13+
14+
Buffer& operator=(const Buffer&) = default;
15+
Buffer& operator=(Buffer&&) noexcept = default;
16+
17+
Nz::MovableLiteral<int, -1> bufferIndex;
18+
};
19+
}
20+
21+
SCENARIO("MovableLiteral", "[MovableValue]")
22+
{
23+
WHEN("testing constructors")
24+
{
25+
Buffer defaultBuffer;
26+
CHECK(defaultBuffer.bufferIndex == -1);
27+
28+
Buffer initializedBuffer(1);
29+
CHECK(initializedBuffer.bufferIndex == 1);
30+
}
31+
32+
WHEN("Testing copy constructor")
33+
{
34+
Buffer foo(42);
35+
Buffer bar(foo);
36+
37+
CHECK(foo.bufferIndex == 42);
38+
CHECK(bar.bufferIndex == 42);
39+
}
40+
41+
WHEN("Testing move constructor")
42+
{
43+
Buffer foo(42);
44+
Buffer bar(std::move(foo));
45+
46+
CHECK(foo.bufferIndex == -1);
47+
CHECK(bar.bufferIndex == 42);
48+
}
49+
50+
WHEN("Testing copy assignation")
51+
{
52+
Buffer foo(42);
53+
Buffer bar;
54+
55+
bar = foo;
56+
57+
CHECK(foo.bufferIndex == 42);
58+
CHECK(bar.bufferIndex == 42);
59+
}
60+
61+
WHEN("Testing move assignation")
62+
{
63+
Buffer foo(42);
64+
Buffer bar;
65+
66+
bar = std::move(foo);
67+
68+
CHECK(foo.bufferIndex == -1);
69+
CHECK(bar.bufferIndex == 42);
70+
}
71+
}
72+
73+
namespace
74+
{
75+
struct Foo
76+
{
77+
Nz::MovableValue<CopyCounter> copyCounter;
78+
};
79+
}
80+
81+
SCENARIO("MovableValue", "[MovableValue]")
82+
{
83+
WHEN("Testing copy constructor")
84+
{
85+
Foo foo;
86+
Foo bar(foo);
87+
88+
CHECK(bar.copyCounter.Get().GetCopyCount() == 1);
89+
CHECK(bar.copyCounter.Get().GetMoveCount() == 0);
90+
}
91+
92+
WHEN("Testing move constructor")
93+
{
94+
Foo foo;
95+
Foo bar(std::move(foo));
96+
97+
CHECK(bar.copyCounter.Get().GetCopyCount() == 0);
98+
CHECK(bar.copyCounter.Get().GetMoveCount() == 1);
99+
}
100+
101+
WHEN("Testing copy assignation")
102+
{
103+
Foo foo;
104+
Foo bar;
105+
106+
bar = foo;
107+
108+
CHECK(bar.copyCounter.Get().GetCopyCount() == 1);
109+
CHECK(bar.copyCounter.Get().GetMoveCount() == 0);
110+
}
111+
112+
WHEN("Testing move assignation")
113+
{
114+
Foo foo;
115+
Foo bar;
116+
117+
bar = std::move(foo);
118+
119+
CHECK(bar.copyCounter.Get().GetCopyCount() == 0);
120+
CHECK(bar.copyCounter.Get().GetMoveCount() == 1);
121+
}
122+
}

0 commit comments

Comments
 (0)