/* This file is part of Clementine. Copyright 2016, John Maguire Clementine is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Clementine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Clementine. If not, see . */ #ifndef LAZY_H #define LAZY_H #include #include // Helper for lazy initialisation of objects. // Usage1: // Lazy my_lazy_object([]() { return new Foo; }); // Usage2: // Lazy my_lazy_object([]() { return new Foo; }, // [](Foo *foo) { delete foo; }); // Note: the Lazy::default_deleter just deletes the object. The default // unique_ptr would have a specialization for arrays. The second usage // should be used with arrays. // template class Lazy { public: explicit Lazy(std::function init, std::function deleter = Lazy::default_deleter) : init_(init), ptr_(nullptr, deleter) {} // Convenience constructor that will lazily default construct the object. Lazy() : init_([]() { return new T; }), ptr_(nullptr, Lazy::default_deleter) {} T* get() const { CheckInitialised(); return ptr_.get(); } typename std::add_lvalue_reference::type operator*() const { CheckInitialised(); return *ptr_; } T* operator->() const { return get(); } // Returns true if the object is not yet initialised. explicit operator bool() const { return ptr_; } // Deletes the underlying object and will re-run the initialisation function // if the object is requested again. void reset() { ptr_.reset(nullptr); } static void default_deleter(T* obj) { delete obj; } private: void CheckInitialised() const { if (!ptr_) { ptr_.reset(init_()); } } const std::function init_; mutable std::unique_ptr> ptr_; }; #endif // LAZY_H