2012-04-14 28 views

回答

2

實際上,你可以寫一個做到這一點的一般包裝:

template <typename T> 
class Lazy { 
public: 
    explicit Lazy(T const& t): _loader(), _item(t) {} 
    explicit Lazy(T&& t): _loader() _item(t) {} 
    explicit Lazy(std::function<T()> l): _loader(l), _item() {} 

    T& operator*() { return this->get(); } 
    T const& operator*() const { return this->get(); } 

    T* operator->() { return &this->get(); } 
    T const* operator->() const { return &this->get(); } 

private: 
    T& get() { if (not _item) { _item = _loader(); } return *_item; } 
    T const& get() const { if (not _item) { _item = _loader(); } return *_item; } 

    std::function<T()> _loader; 
    mutable boost::optional<T> _item; 
}; // class Lazy 

此類保證裝載機被執行一次,只要它完成。如果沒有完成,那麼執行將在下一次訪問時重試。它不是線程安全的。

用法:

// Output prime numbers as text 
bool isPrime(int); 
std::string toEnglish(int); 

void print(int i, Lazy<std::string> const& heavy) { 
    if (not isPrime(i)) { return; } 

    std::cout << *heavy << "\n"; 
} 

int main(int argc, char* argv[]) { 
    if (argc < 2) { return 1; } 

    int max = atoi(argv[1]); 
    for (int i = 2; i <= max; ++i) { 
     print(i, [=](){ return toEnglish(i); }); 
       // ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++11 lambda syntax 
    } 
} 

這裏,toEnglish只會被調用的素數。

+0

謝謝,你能提供一個關於如何使用它的例子嗎?我可以編譯它,但不知道如何使用。 – fxam 2012-04-16 21:07:15

+0

@fxam:當然,在這裏你去:) – 2012-04-17 06:50:49

+0

'get()'是私人的,所以你不能只在'print'中使用它。 :)我把'private:'下移兩行,因爲我認爲這就是你實際的意圖。否則還原。我也改變了lambda,因爲你需要真正抓住'i'。 – Xeo 2012-04-17 07:26:27