你可以混合宏和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'看起來很吸引 –