Вы можете смешивать макросы и лямбды, чтобы создать этот эффект
вы могли бы иметь тип, ленивый
template<class T>
class lazy {
...
}
и тогда вы могли бы иметь LAZY обертку, который создал один из них с помощью лямбда
#define LAZY(E) my_lazy_type<decltype((E))>([&](){ return E; })
Все потребности my_lazy_type - это конструктор, который принимает функцию std :: и перегрузку оператора(), который оценивает и возвращает это. При каждой оценке вы можете заменить thunk на thunk, который просто возвращает уже вычисленное значение, и, таким образом, он будет вычисляться только один раз.
Редактировать: вот пример того, о чем я говорю. Однако я хотел бы отметить, что это не прекрасный пример. он проходит вокруг кучу вещей по стоимости в стороне от ленивых, которые могут полностью победить цель сделать все это в первую очередь. Он использует mutable внутри этого, потому что мне нужно иметь возможность memoize thunk в случаях const. Это можно было бы улучшить во многих отношениях, но это достойное доказательство концепции.
#include <iostream>
#include <functional>
#include <memory>
#include <string>
#define LAZY(E) lazy<decltype((E))>{[&](){ return E; }}
template<class T>
class lazy {
private:
struct wrapper {
std::function<T()> thunk;
wrapper(std::function<T()>&& x)
: thunk(std::move(x)) {}
wrapper(const std::function<T()>& x)
: thunk(x) {}
};
//anytime I see mutable, I fill a bit odd
//this seems to be warented here however
mutable std::shared_ptr<wrapper> thunk_ptr;
public:
lazy(std::function<T()>&& x)
: thunk_ptr(std::make_shared<wrapper>(std::move(x))) {}
T operator()() const {
T val = thunk_ptr->thunk();
thunk_ptr->thunk = [val](){return val;};
return val;
}
};
void log(const lazy<std::string>& msg) {
std::cout << msg() << std::endl;
}
int main() {
std::string hello = "hello";
std::string world = "world";
log(LAZY(hello + ", " + world + "!"));
return 0;
}
Что? [[filler]] –
Лучший способ делать такие вещи, как этот IMO, - это макросы, чтобы избежать создания сообщения, которое нужно передать, если это не нужно. (см. макрос 'assert') –
Использование' static if' выглядит привлекательным –