aboutsummaryrefslogtreecommitdiffstats
path: root/util/generic/lazy_value.h
blob: 033b46eaf2360b55e5bfeb3963b8d86bb177fbb8 (plain) (blame)
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
62
63
64
65
66
#pragma once 
 
#include "maybe.h" 
#include "function.h"
 
template <class T> 
class TLazyValueBase {
public: 
    using TInitializer = std::function<T()>;
 
    TLazyValueBase() = default;

    TLazyValueBase(TInitializer initializer)
        : Initializer(std::move(initializer))
    { 
    } 
 
    explicit operator bool() const noexcept { 
        return Defined(); 
    } 
 
    bool Defined() const noexcept { 
        return ValueHolder.Defined(); 
    } 
 
    const T& GetRef() const { 
        if (!Defined()) { 
            InitDefault(); 
        } 
        return *ValueHolder; 
    } 
 
    const T& operator*() const { 
        return GetRef(); 
    } 
 
    const T* operator->() const { 
        return &GetRef(); 
    } 
 
    void InitDefault() const { 
        Y_ASSERT(Initializer);
        ValueHolder = Initializer(); 
    } 
 
private: 
    mutable TMaybe<T> ValueHolder; 
    TInitializer Initializer; 
}; 
 
// we need this to get implicit construction TLazyValue from lambda
// and save default copy constructor and operator= for type TLazyValue
template <class T>
class TLazyValue: public TLazyValueBase<T> {
public:
    template <typename... TArgs>
    TLazyValue(TArgs&&... args)
        : TLazyValueBase<T>(std::forward<TArgs>(args)...)
    {
    }
};

template <typename F>
TLazyValue<TFunctionResult<F>> MakeLazy(F&& f) {
    return {std::forward<F>(f)};
}