// // Copyright (c) 2012-2020 Kris Jusiak (kris at jusiak dot net) // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #include "boost/di/extension/scopes/shared.hpp" #include namespace di = boost::di; //<- template static auto& calls() { static auto i = 0; return i; } class ctor; class dtor; struct interface1 { virtual ~interface1() noexcept = default; virtual void dummy() = 0; }; struct implementation1 : interface1 { implementation1() { calls()++; } implementation1(const implementation1&) { calls()++; } implementation1(implementation1&&) { calls()++; } ~implementation1() { calls()++; } void dummy() override {} }; struct implementation2 : interface1 { implementation2() { calls()++; } implementation2(const implementation2&) { calls()++; } implementation2(implementation2&&) { calls()++; } ~implementation2() { calls()++; } void dummy() override {} }; struct implementation3 : interface1 { implementation3() { calls()++; } implementation3(const implementation3&) { calls()++; } implementation3(implementation3&&) { calls()++; } ~implementation3() { calls()++; } void dummy() override {} }; //-> auto name = [] {}; class example { public: BOOST_DI_INJECT(example, (named = name) std::shared_ptr sp1, (named = name) std::shared_ptr sp2, std::shared_ptr sp3) { assert(sp1 == sp2); assert(dynamic_cast(sp1.get())); assert(dynamic_cast(sp2.get())); assert(dynamic_cast(sp3.get())); } }; int main() { { // clang-format off auto injector = di::make_injector( di::bind().to().in(di::extension::shared) // di::unique will fail (sp1 == sp2) , di::bind().to().named(name).in(di::extension::shared) ); // clang-format on injector.create(); } { // clang-format off di::injector> injector = di::make_injector( di::bind().to().in(di::extension::shared) ); // clang-format on injector.create>(); // injector.create>(); // error, std::unique_ptr is not exposed } { // clang-format off di::injector), std::shared_ptr> injector = di::make_injector( di::bind().to().in(di::extension::shared).named(name) , di::bind().to().in(di::extension::shared).named(name)[di::override] , di::bind().to().in(di::extension::shared) ); // clang-format on injector.create(); } { // clang-format off auto injector1 = di::make_injector(di::bind().to().in(di::extension::shared)); // clang-format on auto i1 = injector1.create>(); auto injector2 = di::make_injector(std::move(injector1)); // check whether shared scope was successfully moved assert(i1 == injector2.create>()); } calls() = 0; calls() = 0; calls() = 0; calls() = 0; calls() = 0; calls() = 0; { // clang-format off const auto injector = di::make_injector( di::bind().in(di::singleton) /// explicit singleton scope , di::bind().in(di::extension::shared) /// explicit shared scope , di::bind().to() /// deduced shared scope ); // clang-format on injector.create(); injector.create(); assert(dynamic_cast(injector.create>().get())); assert((calls() == 2)); assert((calls() == 1)); assert((calls() == 2)); assert((calls() == 1)); assert((calls() == 1)); assert((calls() == 0)); } // injector dies assert((calls() == 2)); assert((calls() == 1)); // not destroyed assert((calls() == 2)); assert((calls() == 2)); // explicit scope destroyed with injector assert((calls() == 1)); assert((calls() == 1)); // deduced scope destroyed with config/injector }