Skip to content

Instantly share code, notes, and snippets.

@andijcr
Last active March 7, 2019 08:48
Show Gist options
  • Save andijcr/405bf98c60987165deda8fc358bfa349 to your computer and use it in GitHub Desktop.
Save andijcr/405bf98c60987165deda8fc358bfa349 to your computer and use it in GitHub Desktop.
lazy_loading::DelayProxy : an approach to delay the creation of an object while still permitting to code with it
#include <functional>
#include <memory>
#include <optional>
#include <type_traits>
#include <utility>
namespace lazy {
template <typename T> class DelayProxy {
std::unique_ptr<T> subject{};
public:
template <typename... P> void setup(P &&... v) {
subject = std::make_unique<T>(std::forward<P>(v)...);
}
void reset() { subject.reset(); }
template <typename Fn, typename FnRet = std::invoke_result_t<Fn, T &>,
typename Ret = std::conditional_t<!std::is_void_v<FnRet>, std::optional<FnRet>, void>>
auto operator()(Fn fun) noexcept(std::is_nothrow_invocable_v<Fn, T &>)
-> Ret {
if (subject)
return std::invoke(fun, *subject);
if constexpr (!std::is_void_v<FnRet>)
return Ret{};
}
};
}
#include "lazy_proxy.h"
#include <iostream>
using namespace lazy;
struct SomeClass {
int a;
int c;
SomeClass(int _a, int _c) : a{_a}, c{_c} {}
};
void fun() {
DelayProxy<SomeClass> delay;
auto res = delay([&](auto &sc) -> int {
std::cout << "not invoked\n";
std::cout << sc.a << " " << sc.c << "\n";
return sc.a + sc.c;
});
std::cout << res.value_or(-1) << "\n";
delay.setup(3, 2);
delay([&](auto &sc) {
std::cout << "actually invoked\n";
std::cout << sc.a << " " << sc.c << "\n";
});
auto res_v = delay([&](auto &sc) -> int {
std::cout << "actually invoked\n";
sc.a *= 3;
std::cout << sc.a << " " << sc.c << "\n";
return sc.a + sc.c;
});
std::cout << res_v.value_or(-1) << "\n";
delay.setup(7, 11);
delay([&](auto &sc) {
std::cout << "actually invoked\n";
std::cout << sc.a << " " << sc.c << "\n";
});
std::cout << "now will reset\n";
delay.reset();
auto res_v2 = delay([&](auto &sc) -> int {
std::cout << "again, not invoked\n";
sc.a *= 3;
std::cout << sc.a << " " << sc.c << "\n";
return sc.a + sc.c;
});
std::cout << res_v2.value_or(-1) << "\n";
}
int main(){
fun();
}
$ ./lazy_loading
-1
actually invoked
3 2
actually invoked
9 2
11
actually invoked
7 11
now will reset
-1
$
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment