这段代码运行良好:
// 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
我从尝试许多(很多)设置(包括完全放弃工厂)中了解到的是,您根本不应该(智能)将指针绑定到原语,这也是工厂最终要做的事情。您应该将指针绑定到接口。
您可以通过将指针包装在值类型中来欺骗系统,如下所示:
#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)