|
||||
File indexing completed on 2024-04-06 12:01:18
0001 #ifndef CommonTools_Utils_LazyResult_h 0002 #define CommonTools_Utils_LazyResult_h 0003 // -*- C++ -*- 0004 // 0005 // Package: CommonTools/Utils 0006 // Class : LazyResult 0007 // 0008 /**\class LazyResult LazyResult.h "CommonTools/Utils/interface/LazyResult.h" 0009 Description: Wrapper around a function call for lazy execution. 0010 0011 Usage: 0012 // example: lazy addition 0013 auto result = LazyResult(std::plus<int>, x, x); 0014 std::cout << result.value() << std::endl; 0015 0016 Notes: 0017 * The arguments for the delayed call are stored by reference (watch their 0018 lifetime). 0019 * The overhead in memory compared to just storing the result is small: one 0020 reference per argument, one bool flag and a function pointer (on my system: 0021 1 byte for lambda function, 8 bytes for global function and 16 bytes for 0022 member function due to possible index to virtual table). 0023 0024 Implementation: 0025 0026 * For the Args... we explicitly add const& (also in the the args_ tuple). 0027 Otherwise, the arguments will be stored by value which comes with too much 0028 overhead. This implies that the lifetime of the arguments passed to 0029 LazyResult neet to live longer than the LazyResult instance. Function pointers 0030 are small, so no need for const& to the Func. 0031 * An alternative to using a ::value() member function to get the result could 0032 be a cast operator: operator Result const &(). This might be pretty because 0033 the result is automatically evaluated the first time you try to bind it to 0034 a Result const &. I think this would however be too implicit and dangerous. 0035 0036 */ 0037 // 0038 // Original Author: Jonas Rembser 0039 // Created: Mon, 14 Jun 2020 00:00:00 GMT 0040 // 0041 0042 #include <tuple> 0043 #include <type_traits> 0044 0045 template <class Func, class... Args> 0046 class LazyResult { 0047 public: 0048 using Result = typename std::invoke_result<Func, Args...>::type; 0049 0050 LazyResult(Func func, Args const&... args) : func_(func), args_(args...) {} 0051 0052 Result const& value() { 0053 if (!evaluated_) { 0054 evaluate(); 0055 } 0056 return result_; 0057 } 0058 0059 private: 0060 void evaluate() { evaluateImpl(std::make_index_sequence<sizeof...(Args)>{}); } 0061 0062 template <std::size_t... ArgIndices> 0063 void evaluateImpl(std::index_sequence<ArgIndices...>) { 0064 result_ = func_(std::get<ArgIndices>(args_)...); 0065 evaluated_ = true; 0066 } 0067 0068 // having evaluated_ and the potentially small func_ together might 0069 // save alignemnt bits (e.g. a lambda function is just 1 byte) 0070 bool evaluated_ = false; 0071 Func func_; 0072 std::tuple<Args const&...> args_; 0073 Result result_; 0074 }; 0075 0076 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.2.1 LXR engine. The LXR team |