문제

I would like to obey Law of Demeter. But I would also like to lazy load some objects passed to constructors. How should I implement that? Pass a wrapper class? Pass a function pointer?

도움이 되었습니까?

해결책

You can actually write a generic wrapper that accomplish this:

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

This class guarantees that the loader is executed once, as long as it completes. If it does not complete, then execution will be retried on the next access. It is not thread-safe.

Usage:

// 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
    }
}

Here, toEnglish is only ever invoked for prime numbers.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top