boost::ext:di通过工厂扩展创建带有shared_ptr参数的对象

问题描述 投票:0回答:1

这段代码运行良好:

// g++ --version == 13.2.1
// g++ -O0 -g3 -std=gnu++20 -Wall -Wextra -Wpedantic -Werror -Wfatal-errors

#include <boost/di/extension/injections/factory.hpp>
#include <cassert>
#include <memory>

class Interface
{
public:
    virtual ~Interface() noexcept = default;
};

class Implementation : public Interface
{
public:
    Implementation(int value) : value_(value) {}
    int value_ = 0;
};

class Example
{
public:
    Example(const boost::di::extension::ifactory<Interface, int>& f)
    {
        auto impl = f.create(87);
        assert(dynamic_cast<Implementation*>(impl.get()));
    }
};

namespace di = boost::di;

int main()
{
    auto injector = di::make_injector(di::bind<di::extension::ifactory<Interface, int>>().to(
        di::extension::factory<Implementation>()));
    auto example = injector.create<std::unique_ptr<Example>>();
    assert(example);
}

但是这个不能编译:

#include <boost/di/extension/injections/factory.hpp>
#include <cassert>
#include <memory>

class Interface
{
public:
    virtual ~Interface() noexcept = default;
};

class Implementation : public Interface
{
public:
    Implementation(std::shared_ptr<int> value) : value_(move(value)) {}
    std::shared_ptr<int> value_;
};

class Example
{
public:
    Example(const boost::di::extension::ifactory<Interface, std::shared_ptr<int>>& f)
    {
        auto ptr = std::make_shared<int>(87);
        auto impl = f.create(std::shared_ptr<int>(ptr));  // can i just pass `ptr` ?
        assert(dynamic_cast<Implementation*>(impl.get()));
    }
};

namespace di = boost::di;

int main()
{
    auto injector =
        di::make_injector(di::bind<di::extension::ifactory<Interface, std::shared_ptr<int>>>().to(
            di::extension::factory<Implementation>()));
    auto example = injector.create<std::unique_ptr<Example>>();
    assert(example);
}

输出是:

In file included from /deps/di/extension/include/boost/di/extension/injections/factory.hpp:11,
                 from /test.cpp:1:
/deps/di/include/boost/di.hpp: In instantiation of ‘struct boost::ext::di::v1_3_0::aux::concept_check<boost::ext::di::v1_3_0::concepts::type_<std::shared_ptr<int> >::has_disallowed_qualifiers>’:
/deps/di/include/boost/di.hpp:1998:9:   required from ‘std::unique_ptr<I> boost::ext::di::v1_3_0::extension::factory_impl<TInjector, T, boost::ext::di::v1_3_0::extension::ifactory<I, TArgs ...> >::create(TArgs&& ...) const [with TInjector = boost::ext::di::v1_3_0::core::injector<boost::ext::di::v1_3_0::config, boost::ext::di::v1_3_0::core::pool<boost::ext::di::v1_3_0::aux::type_list<> >, boost::ext::di::v1_3_0::core::dependency<boost::ext::di::v1_3_0::scopes::instance, boost::ext::di::v1_3_0::extension::ifactory<Interface, std::shared_ptr<int> >, boost::ext::di::v1_3_0::extension::factory<Implementation>, boost::ext::di::v1_3_0::no_name, void, boost::ext::di::v1_3_0::core::none> >; T = Implementation; I = Interface; TArgs = {std::shared_ptr<int>}]’
/deps/di/extension/include/boost/di/extension/injections/factory.hpp:30:22:   required from here
/deps/di/include/boost/di.hpp:379:20: error: static assertion failed: constraint not satisfied
  379 |   static_assert(T::value, "constraint not satisfied");
      |                    ^~~~~
/deps/di/include/boost/di.hpp:379:20: note: ‘boost::ext::di::v1_3_0::aux::integral_constant<bool, false>::value’ evaluates to false
/deps/di/include/boost/di.hpp: In instantiation of ‘std::unique_ptr<I> boost::ext::di::v1_3_0::extension::factory_impl<TInjector, T, boost::ext::di::v1_3_0::extension::ifactory<I, TArgs ...> >::create(TArgs&& ...) const [with TInjector = boost::ext::di::v1_3_0::core::injector<boost::ext::di::v1_3_0::config, boost::ext::di::v1_3_0::core::pool<boost::ext::di::v1_3_0::aux::type_list<> >, boost::ext::di::v1_3_0::core::dependency<boost::ext::di::v1_3_0::scopes::instance, boost::ext::di::v1_3_0::extension::ifactory<Interface, std::shared_ptr<int> >, boost::ext::di::v1_3_0::extension::factory<Implementation>, boost::ext::di::v1_3_0::no_name, void, boost::ext::di::v1_3_0::core::none> >; T = Implementation; I = Interface; TArgs = {std::shared_ptr<int>}]’:
/deps/di/extension/include/boost/di/extension/injections/factory.hpp:30:22:   required from here
/deps/di/include/boost/di.hpp:1998:9: error: no type named ‘type’ in ‘struct boost::ext::di::v1_3_0::aux::concept_check<boost::ext::di::v1_3_0::concepts::type_<std::shared_ptr<int> >::has_disallowed_qualifiers>’
 1998 |         bind
      |         ^~~~

如何修复此代码?谢谢您的回复。

问候,

XS

c++ boost c++17 boost-extension
1个回答
0
投票

我从尝试许多(很多)设置(包括完全放弃工厂)中了解到的是,您根本不应该(智能)将指针绑定到原语,这也是工厂最终要做的事情。您应该将指针绑定到接口

您可以通过将指针包装在值类型中来欺骗系统,如下所示:

实时编译器资源管理器

#include "https://raw.githubusercontent.com/boost-ext/di/cpp14/include/boost/di.hpp"
#include <cassert>
#include <iostream>
#include <memory>
namespace di = boost::di;

template <typename T> struct Wrapped {
    std::shared_ptr<T> value;
    explicit Wrapped(T v = {}) : value(std::make_shared<T>(std::move(v))) {}

    // for debug output
    friend std::ostream& operator<<(std::ostream& os, Wrapped const& a) {
        return a.value ? os << *a.value : os << "#";
    }
};

// using Arg = int;
using Arg = Wrapped<int>;

struct Interface {
    virtual ~Interface() noexcept = default;
};

struct Implementation : Interface {
    Implementation(Arg value) : value_(std::move(value)) {
        std::cout << __PRETTY_FUNCTION__ << "(" << value_ << ")" << std::endl;
    }
    Arg value_{};
};

struct Example {
    Example(std::unique_ptr<Interface> impl) {
        assert(dynamic_cast<Implementation*>(impl.get()));
    }
};

int main() {
    static_assert(di::concepts::boundable<Arg>::value);

    auto injector = make_injector( //
        di::bind<int>().to(42),    //
        di::bind<Interface>()      //
            .to<Implementation>()  //
    );

    auto example = injector.create<std::unique_ptr<Example>>();
    assert(example);
}

印刷

Implementation::Implementation(Arg)(42)

回到工厂

如果您确实希望注入者实例化动态数量的实例,而不通过引用直接共享整个注入器:

#include <boost/di.hpp>
#include <boost/di/extension/injections/factory.hpp>
#include <cassert>
#include <iostream>
#include <memory>
namespace di = boost::di;

template <typename T> struct Wrapped {
    std::shared_ptr<T> value;
    /*explicit*/ Wrapped(T v = {}) : value(std::make_shared<T>(std::move(v))) {}

    // for debug output
    friend std::ostream& operator<<(std::ostream& os, Wrapped const& a) {
        return a.value ? os << *a.value : os << "#";
    }
};

// using Arg = int;
using Arg = Wrapped<int>;

struct Interface {
    virtual ~Interface() noexcept = default;
};

using TFactory = di::extension::ifactory<Interface>;

struct Implementation : Interface {
    Implementation(Arg value) : value_(std::move(value)) {
        std::cout << __PRETTY_FUNCTION__ << "(" << value_ << ")" << std::endl;
    }
    Arg value_{};
};

struct Example {
    Example(TFactory const& f) {
        std::generate_n(back_inserter(impls), 10, [&f]{ return f.create(); });
    }
    std::vector<std::unique_ptr<Interface>> impls;
};

int main() {
    static_assert(di::concepts::boundable<Arg>::value);

    auto injector = make_injector(                        //
        di::bind<int>().to(43),                           //
        di::bind<TFactory>()                              //
            .to(di::extension::factory<Implementation>()) //
    );

    auto example = injector.create<std::unique_ptr<Example>>();
    assert(example);
}

印刷

Implementation::Implementation(Arg)(43)
Implementation::Implementation(Arg)(43)
Implementation::Implementation(Arg)(43)
Implementation::Implementation(Arg)(43)
Implementation::Implementation(Arg)(43)
Implementation::Implementation(Arg)(43)
Implementation::Implementation(Arg)(43)
Implementation::Implementation(Arg)(43)
Implementation::Implementation(Arg)(43)
Implementation::Implementation(Arg)(43)
Implementation::Implementation(Arg)(43)

并且不受束缚
Arg

当然,只要

Arg
再次满足
boundable
约束,这再次适用于构造函数参数:

using TFactory = di::extension::ifactory<Interface, Arg>;

struct Example {
    Example(TFactory const& f) {
        generate_n(                   //
            back_inserter(impls), 10, //
            [i = 0, &f]() mutable { return f.create(42 * i++); });
    }
    std::vector<std::unique_ptr<Interface>> impls;
};

int main() {
    static_assert(di::concepts::boundable<Arg>::value);

    auto injector = make_injector(                        //
        di::bind<TFactory>()                              //
            .to(di::extension::factory<Implementation>()) //
    );

    auto example = injector.create<std::unique_ptr<Example>>();
    assert(example);
}

印刷

Implementation::Implementation(Arg)(0)
Implementation::Implementation(Arg)(42)
Implementation::Implementation(Arg)(84)
Implementation::Implementation(Arg)(126)
Implementation::Implementation(Arg)(168)
Implementation::Implementation(Arg)(210)
Implementation::Implementation(Arg)(252)
Implementation::Implementation(Arg)(294)
Implementation::Implementation(Arg)(336)
Implementation::Implementation(Arg)(378)
© www.soinside.com 2019 - 2024. All rights reserved.