Made Lazy<T> copyable
This commit is contained in:
parent
17b43ad205
commit
5198ee9230
30
src/Lazy.h
30
src/Lazy.h
|
@ -2,27 +2,38 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
// Class template for lazy initialization.
|
||||||
|
// Copies use reference semantics.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class Lazy {
|
class Lazy {
|
||||||
|
// Shared state between copies
|
||||||
|
struct State {
|
||||||
|
std::function<T()> createValue;
|
||||||
|
std::once_flag initialized;
|
||||||
|
std::unique_ptr<T> value;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
|
|
||||||
explicit Lazy(std::function<T()> createValue) :
|
Lazy() = default;
|
||||||
createValue(createValue)
|
|
||||||
{}
|
explicit Lazy(std::function<T()> createValue) {
|
||||||
|
state->createValue = createValue;
|
||||||
|
}
|
||||||
|
|
||||||
explicit operator bool() const {
|
explicit operator bool() const {
|
||||||
return static_cast<bool>(_value);
|
return static_cast<bool>(state->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
T& value() {
|
T& value() {
|
||||||
init();
|
init();
|
||||||
return *_value;
|
return *state->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T& value() const {
|
const T& value() const {
|
||||||
init();
|
init();
|
||||||
return *_value;
|
return *state->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
T* operator->() {
|
T* operator->() {
|
||||||
|
@ -40,12 +51,11 @@ public:
|
||||||
const T& operator*() const {
|
const T& operator*() const {
|
||||||
return value();
|
return value();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init() const {
|
void init() const {
|
||||||
std::call_once(initialized, [&] { _value = std::make_unique<T>(createValue()); });
|
std::call_once(state->initialized, [&] { state->value = std::make_unique<T>(state->createValue()); });
|
||||||
}
|
}
|
||||||
|
|
||||||
std::function<T()> createValue;
|
std::shared_ptr<State> state = std::make_shared<State>();
|
||||||
mutable std::once_flag initialized;
|
|
||||||
mutable std::unique_ptr<T> _value;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -41,6 +41,24 @@ TEST(Lazy, constUsage) {
|
||||||
EXPECT_TRUE(static_cast<bool>(lazy));
|
EXPECT_TRUE(static_cast<bool>(lazy));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Lazy, copying) {
|
||||||
|
Lazy<Foo> a;
|
||||||
|
int counter = 0;
|
||||||
|
auto createValue = [&] { return counter++; };
|
||||||
|
Lazy<Foo> b(createValue);
|
||||||
|
a = b;
|
||||||
|
EXPECT_EQ(0, counter);
|
||||||
|
EXPECT_FALSE(static_cast<bool>(a));
|
||||||
|
EXPECT_FALSE(static_cast<bool>(b));
|
||||||
|
EXPECT_EQ(0, a->value);
|
||||||
|
EXPECT_EQ(1, counter);
|
||||||
|
EXPECT_TRUE(static_cast<bool>(a));
|
||||||
|
EXPECT_TRUE(static_cast<bool>(b));
|
||||||
|
EXPECT_EQ(0, b->value);
|
||||||
|
Lazy<Foo> c(createValue);
|
||||||
|
EXPECT_EQ(1, c->value);
|
||||||
|
}
|
||||||
|
|
||||||
using Expensive = Foo;
|
using Expensive = Foo;
|
||||||
#define member value;
|
#define member value;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue