Added class Lazy<T>
This commit is contained in:
parent
ddcadad710
commit
17b43ad205
|
@ -224,6 +224,7 @@ set(SOURCE_FILES
|
||||||
src/tupleHash.h
|
src/tupleHash.h
|
||||||
src/ThreadPool.cpp src/ThreadPool.h
|
src/ThreadPool.cpp src/ThreadPool.h
|
||||||
src/ObjectPool.h
|
src/ObjectPool.h
|
||||||
|
src/Lazy.h
|
||||||
)
|
)
|
||||||
add_executable(rhubarb ${SOURCE_FILES})
|
add_executable(rhubarb ${SOURCE_FILES})
|
||||||
target_link_libraries(rhubarb ${Boost_LIBRARIES} cppFormat sphinxbase pocketSphinx flite webRTC)
|
target_link_libraries(rhubarb ${Boost_LIBRARIES} cppFormat sphinxbase pocketSphinx flite webRTC)
|
||||||
|
@ -239,6 +240,7 @@ set(TEST_FILES
|
||||||
tests/pairsTests.cpp
|
tests/pairsTests.cpp
|
||||||
tests/tokenizationTests.cpp
|
tests/tokenizationTests.cpp
|
||||||
tests/g2pTests.cpp
|
tests/g2pTests.cpp
|
||||||
|
tests/LazyTests.cpp
|
||||||
src/stringTools.cpp src/stringTools.h
|
src/stringTools.cpp src/stringTools.h
|
||||||
src/Timeline.h
|
src/Timeline.h
|
||||||
src/TimeRange.cpp src/TimeRange.h
|
src/TimeRange.cpp src/TimeRange.h
|
||||||
|
@ -249,6 +251,7 @@ set(TEST_FILES
|
||||||
src/g2p.cpp src/g2p.h
|
src/g2p.cpp src/g2p.h
|
||||||
src/logging.cpp src/logging.h
|
src/logging.cpp src/logging.h
|
||||||
src/tools.cpp src/tools.h
|
src/tools.cpp src/tools.h
|
||||||
|
src/Lazy.h
|
||||||
)
|
)
|
||||||
add_executable(runTests ${TEST_FILES})
|
add_executable(runTests ${TEST_FILES})
|
||||||
target_link_libraries(runTests gtest gmock gmock_main flite cppFormat)
|
target_link_libraries(runTests gtest gmock gmock_main flite cppFormat)
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
#pragma once
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Lazy {
|
||||||
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
|
||||||
|
explicit Lazy(std::function<T()> createValue) :
|
||||||
|
createValue(createValue)
|
||||||
|
{}
|
||||||
|
|
||||||
|
explicit operator bool() const {
|
||||||
|
return static_cast<bool>(_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
T& value() {
|
||||||
|
init();
|
||||||
|
return *_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& value() const {
|
||||||
|
init();
|
||||||
|
return *_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* operator->() {
|
||||||
|
return &value();
|
||||||
|
}
|
||||||
|
|
||||||
|
const T* operator->() const {
|
||||||
|
return &value();
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator*() {
|
||||||
|
return value();
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& operator*() const {
|
||||||
|
return value();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void init() const {
|
||||||
|
std::call_once(initialized, [&] { _value = std::make_unique<T>(createValue()); });
|
||||||
|
}
|
||||||
|
|
||||||
|
std::function<T()> createValue;
|
||||||
|
mutable std::once_flag initialized;
|
||||||
|
mutable std::unique_ptr<T> _value;
|
||||||
|
};
|
|
@ -0,0 +1,58 @@
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
#include "Lazy.h"
|
||||||
|
|
||||||
|
using namespace testing;
|
||||||
|
using std::make_unique;
|
||||||
|
|
||||||
|
// Not copyable, no default constrctor, movable
|
||||||
|
struct Foo {
|
||||||
|
const int value;
|
||||||
|
Foo(int value) : value(value) {}
|
||||||
|
|
||||||
|
Foo() = delete;
|
||||||
|
Foo(const Foo&) = delete;
|
||||||
|
Foo& operator=(const Foo &) = delete;
|
||||||
|
|
||||||
|
Foo(Foo&&) = default;
|
||||||
|
Foo& operator=(Foo&&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(Lazy, basicUsage) {
|
||||||
|
bool lambdaCalled = false;
|
||||||
|
Lazy<Foo> lazy([&lambdaCalled] { lambdaCalled = true; return Foo(42); });
|
||||||
|
EXPECT_FALSE(lambdaCalled);
|
||||||
|
EXPECT_FALSE(static_cast<bool>(lazy));
|
||||||
|
EXPECT_EQ(42, (*lazy).value);
|
||||||
|
EXPECT_EQ(42, lazy.value().value);
|
||||||
|
EXPECT_EQ(42, lazy->value);
|
||||||
|
EXPECT_TRUE(lambdaCalled);
|
||||||
|
EXPECT_TRUE(static_cast<bool>(lazy));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Lazy, constUsage) {
|
||||||
|
bool lambdaCalled = false;
|
||||||
|
const Lazy<Foo> lazy([&lambdaCalled] { lambdaCalled = true; return Foo(42); });
|
||||||
|
EXPECT_FALSE(lambdaCalled);
|
||||||
|
EXPECT_FALSE(static_cast<bool>(lazy));
|
||||||
|
EXPECT_EQ(42, (*lazy).value);
|
||||||
|
EXPECT_EQ(42, lazy.value().value);
|
||||||
|
EXPECT_EQ(42, lazy->value);
|
||||||
|
EXPECT_TRUE(lambdaCalled);
|
||||||
|
EXPECT_TRUE(static_cast<bool>(lazy));
|
||||||
|
}
|
||||||
|
|
||||||
|
using Expensive = Foo;
|
||||||
|
#define member value;
|
||||||
|
|
||||||
|
TEST(Lazy, demo) {
|
||||||
|
// Constructor takes function
|
||||||
|
Lazy<Expensive> lazy([] { return Expensive(42); });
|
||||||
|
|
||||||
|
// Multiple ways to access value
|
||||||
|
Expensive& a = *lazy;
|
||||||
|
Expensive& b = lazy.value();
|
||||||
|
auto c = lazy->member;
|
||||||
|
|
||||||
|
// Check if initialized
|
||||||
|
if (lazy) { /* ... */ }
|
||||||
|
}
|
Loading…
Reference in New Issue