You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修复boost::ext::di工厂扩展传递shared_ptr参数的编译错误

Boost.DI工厂使用智能指针参数编译失败的解决方案

可正常运行的代码

// 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));  // 能否直接传递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
      |         ^~~~

解决方案

1. 编译失败原因

Boost.DI的extension::factory默认会自动解析目标类的构造函数参数,当参数是智能指针这类非原始类型时,注入器会认为该参数应由自身提供而非外部传递,从而触发概念检查失败。我们需要显式告知工厂:构造函数中的std::shared_ptr<int>参数是由create方法外部传入的,而非注入器注入。

2. 修改后的可编译代码

#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_(std::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(ptr);  // 直接传递ptr即可
        assert(dynamic_cast<Implementation*>(impl.get()));
        assert(*impl->value_ == 87); // 验证参数传递正确
    }
};

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, std::shared_ptr<int>>())); // 显式指定外部传递的参数类型
    auto example = injector.create<std::unique_ptr<Example>>();
    assert(example);
}

3. 修改点说明

  • 绑定工厂时显式指定参数类型:将di::extension::factory<Implementation>()改为di::extension::factory<Implementation, std::shared_ptr<int>>(),明确告诉Boost.DI该工厂需要外部传入std::shared_ptr<int>类型的参数。
  • 直接传递ptr到create方法:create方法支持完美转发,传递左值ptr会触发拷贝构造,传递std::move(ptr)会触发移动构造,无需显式构造新的std::shared_ptr<int>。

关于f.create传递参数的疑问

可以直接传递ptr,无需显式构造新的std::shared_ptr<int>。create方法的参数是可变参数模板TArgs&&...,支持完美转发:

  • 传递ptr(左值):会调用std::shared_ptr的拷贝构造函数,增加引用计数。
  • 传递std::move(ptr)(右值):会调用std::shared_ptr的移动构造函数,不会增加引用计数,效率更高。

内容的提问来源于stack exchange,提问作者SVA522

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 02:07:05