你可以混合宏和lambda表达式来产生这种效果
你可以有一个类型,懒惰
template<class T>
class lazy {
...
}
,然后你可以有一个使用Lambda
创建的其中一个慵懒的包装
#define LAZY(E) my_lazy_type<decltype((E))>([&](){ return E; })
所有my_lazy_type需求都是一个接受std :: function的构造函数,以及一个operator()的重载函数,用于计算并返回它。在每次评估中,您可以用一个只返回已经计算的值的thunk替换该thunk,因此它只会计算一次。
编辑: 这里是我正在谈论的一个例子。不过,我想指出,这不是一个完美的例子。它通过价值在一堆懒散的东西中传递了一堆东西,这可能完全破坏了首先这样做的目的。它内部使用可变内存,因为我需要能够在常量情况下记忆thunk。这可以在许多方面得到改善,但它是一个体面的概念证明。
#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]] –
做这样的事情的最佳方法就是使用宏,以避免在不需要的情况下构建要传递的消息。 (参见'assert'宏) –
使用'static if'看起来很吸引 –