Design

Component Description
Bindings DSL to create dependencies representation which will be used by core to resolve types
Scopes Responsible for maintain objects life time
Providers Responsible for providing object instance
Policies Compile-time limitations for types / Run-time types vistor
Config Configuration for [Policies] and [Providers]
Core Responsible for resolving requested types (implementation detail)
Wrappers Responsible for conversion to required type (implementation detail)

Let's assume all examples below include boost/di.hpp header and define a convenient di namespace alias as well as some basic interfaces and types.

#include <boost/di.hpp>
namespace di = boost::di;

struct i1 { virtual ~i1() = default; virtual void dummy1() = 0; };
struct i2 { virtual ~i2() = default; virtual void dummy2() = 0; };
struct impl1 : i1 { void dummy1() override { } };
struct impl2 : i2 { void dummy2() override { } };
struct impl : i1, i2 { void dummy1() override { } void dummy2() override { } };

Injector

Injector is a core component providing types creation functionality using bindings.

--- di::make_injector ---

Header

#include <boost/di.hpp>

Description

Creates injector type.

Semantics

template<class... TDeps> requires boundable<TDeps...>
class injector {
public:
  using deps; // list of dependencies
  using config; // configuration

  injector(injector&&) = default;
  template <class... Ts> // no requirements
  injector(core::injector<Ts...>&&) noexcept;
  explicit injector(const TDeps&...) noexcept;

  template <class T>
  injector& operator=(T&& other) noexcept;

  template<class T> requires creatable<T>
  T create() const;
};
Expression Requirement Description Returns
TDeps... boundable<TDeps...> Bindings to be used as configuration -
create<T>() creatable<T> Creates type T T
Type T Is allowed? Note
T -
T* Ownership transfer!
const T* Ownership transfer!
T& -
const T& Reference with singleton / Temporary with unique
T&& -
std::unique_ptr<T> -
std::shared_ptr<T> -
std::weak_ptr<T> -
boost_shared_ptr<T> -
template<
  class TConfig = di::config
, class... TBindings
> requires configurable<TConfig> && boundable<TBindings...>
auto make_injector(TBindings...) noexcept;
Expression Requirement Description Returns
TConfig configurable<TConfig> Configuration per injector -
make_injector(TBindings...) boundable<TBindings...> Creates injector with given Bindings injector

Test CPP(SPLIT) Example

CPP(BTN) CPP(BTN)



Injection in a nutshell (implementation detail)

The main interface of the injector is a create method. When create method is called for type T the magic happens. Firstly, policies are verified (for example, whether the type T is allowed to be created). Then, the constructor traits are deduced (ctor_traits ) for type T and dependencies of the constructor parameters are resolved (binder). wrapper is used to convert internal representation of the dependency into a required type (ex. shared_ptr<T>). Whole process is repeated recursively for all required parameters of T constructor.

struct direct; // T(...)
struct uniform; // T{...}

template<class T, class... TArgs> is_braces_constructible; // type T is constructible using T{...}
template<class T, class... TArgs> is_constructible; // Type T is constructible using T(...)

template<class T> is_injectable; // Type T uses BOOST_DI_INJECT or BOOST_DI_INJECT_TRAITS

template<class TConfig, class... TBindings> // For Example, TBindings = { di::bind<Interface>.to<Implementation> }
struct core::injector : TBindings... {
  using config = TConfig;
  using deps = TBindings...;

  template<class T> // For example, T = Interface
  auto create() const noexcept {
    TConfig::policies<T>()...; // verify policies
    using Type = core::binder<TBindings...>().resolve<T>(*this); // Type = Implementation
    return core::wrapper<T>{dependency.create(provider<TInjector>{*this}.get<Type>())};
  }
};

template<class TInjector, class TConfig>
struct provider {
  template<class T> auto get() const noexcept {
    using pair<TInitialization, TCtor...> = decltype(ctor_traits<TInjector, T>());
    return TConfig::provider().get(TInitialization{}, TCtor...);
  }
  const TInjector& injector;
};

template<class TInjector>
struct any_type {
  template<class T>
  operator T() const {
    return injector.templte create<T>();
  }
  const TInjector& injector;
};

template<class TInjector, class T>
auto ctor_traits() {
  if (is_injectable<T>() {
    return pair<direct, typename T::boost_di_inject__>{}; // BOOST_DI_INJECT(T, args...) -> T(args...)
  }

  for (auto i = BOOST_DI_CFG_CTOR_LIMIT_SIZE; i >= 0; --i) {
    if (is_constructible<T, any_type<TInjector>...>()) { // ... -> i times
      return pair<direct, any_type<TInjector>...>{}; // T(any_type...)
    }
  }

  for (auto i = BOOST_DI_CFG_CTOR_LIMIT_SIZE; i >= 0; --i) {
    if (is_braces_constructible<T, any_type<TInjector>...>()) { // ... -> i times
      return pair<uniform, any_type<TInjector>...>{}; // T{any_type...}
    }
  }

  return error(...);
};

Note

Automatic injection depends on template implicit conversion operator and therefore conversion constructors template<class I> T(I) are not supported and have to be injected using BOOST_DI_INJECT, BOOST_DI_INJECT_TRAITS, di::inject or di::ctor_traits.


Bindings

Bindings define dependencies configuration describing what types will be created and what values will be passed into them.

--- di::bind ---

Header

#include <boost/di.hpp>

Description

Allows to bind interface to implementation and associate value with it.

Semantics

struct override; // overrides given configuration

namespace detail {
  template<class I, class... Is/*any_of*/> requires boundable<I, Is...>
  struct bind {
    bind(bind&&) noexcept = default;

    template <class T> requires !is_array<I> && boundable<I, T>
    auto to() noexcept;

    template <class... Ts> requires is_array<I> && boundable<Ts...>
    auto to() noexcept;

    template<class T> requires boundable<I, T>
    auto to(T&&) noexcept;

    template<class TScope> requires scopable<TScope>
    auto in(const TScope& = di::deduce) noexcept;

    template<class TName> // no requirements
    auto named(const TName& = {}) noexcept;

    auto operator[](const override&) noexcept;
  };
} // detail

template<class... Ts> requires boundable<Ts...>
detail::bind<Ts...> bind{};
Expression Requirement Description Returns
I, Is... boundable<I, Is...> 'Interface' types -
to<T> boundable<T> Binds I, Is... to T type boundable
to<Ts...> boundable<Ts...> Binds I, Is... to Ts... type boundable
to(T&&) boundable<T> Binds I, Is... to T object boundable
in(const TScope&) scopable<TScope> Binds I, Is... in TScope` boundable
named(const TName&) - Binds I, Is... using named annotation boundable
operator[](const override&) - Overrides given binding boundable

Note

Check out also instance scope to read more about binding to values: di::bind<>.to(value).

Expression Description
Multiple Interfaces
di::bind<Interface1, Interface2, ...>.to<Implementation>() Binds Interface1, Interface2, ... to Implementation using one object
Multiple Bindings (std::array, std::vector, std::set)
di::bind<int[]>.to({1, 2, ...}) Binds int to values 1, 2, ...
di::bind<Interface*[]>.to<Implementation1, Implementation2, ...>() Binds Interface to Implementation1, Implementation2, ...
Dynamic Bindings
di::bind<Interface>.to([](const auto& injector)
{ return injector.template create<Implementation>()})
Allows to bind Interface depending on a run-time condition

Test CPP(SPLIT) CPP(SPLIT) CPP(SPLIT) CPP(SPLIT) CPP(SPLIT) CPP(SPLIT) CPP(SPLIT) CPP(SPLIT) CPP(SPLIT) CPP(SPLIT) Example

CPP(BTN) CPP(BTN) CPP(BTN) CPP(BTN) CPP(BTN)





Injections

Constructor Injection is the most powerful of available injections. It guarantees initialized state of data members. [Boost].DI constructor injection is achieved without any additional work from the user.

--- automatic (default) ---

Header

#include <boost/di.hpp>

Description

[Boost].DI will deduce the best available constructor to be used for injection - unique constructor with the longest parameter list. If the default behavior should be changed constructor has to be explicitly marked with BOOST_DI_INJECT or BOOST_DI_INJECT_TRAITS or di::ctor_traits] or di::inject.

Note

Automatic constructor parameters deduction is limited to BOOST_DI_CFG_CTOR_LIMIT_SIZE, which by default is set to 10.

Semantics

class T {
public:
  T(auto parameter1, auto parameter2, ..., auto parameterN);
};
Expression Requirement Description Returns
parameter1-parameterN - N constructor parameter -

Note

[Boost].DI is not able to automatically distinguish between ambiguous constructors with the same (longest) number of parameters. Use BOOST_DI_INJECT or BOOST_DI_INJECT_TRAITS or di::ctor_traits or di::inject to explicitly mark constructor to be injected.

Test CPP(SPLIT) CPP(SPLIT) CPP(SPLIT) CPP(SPLIT) Example

CPP(BTN) CPP(BTN) CPP(BTN) CPP(BTN)





--- BOOST_DI_INJECT ---

Header

#include <boost/di.hpp>

Description

BOOST_DI_INJECT is a macro definition used to explicitly say [Boost].DI which constructor should be used as well as to annotate types - see annotations for further reding. When class has more than one constructor [Boost].DI will by default choose the one with the longest parameter list. In case of constructors ambiguity, [Boost].DI is not able to choose the best one. Then BOOST_DI_INJECT becomes handy to point which constructor should be used.

Semantics

struct T {
    BOOST_DI_INJECT(T, ...) { }
};
Expression Requirement Description Returns
T - Class/Struct name -
... - T constructor parameters -

Note

BOOST_DI_INJECT constructor parameters is limited to BOOST_DI_CFG_CTOR_LIMIT_SIZE, which by default is set to 10.

Test CPP(SPLIT) Example

CPP(BTN) CPP(BTN)



--- BOOST_DI_INJECT_TRAITS ---

Header

#include <boost/di.hpp>

Description

BOOST_DI_INJECT_TRAITS is a macro definition used to define constructor traits.

Semantics

struct T {
  BOOST_DI_INJECT_TRAITS(...) { }
  T(...) { }
};
Expression Requirement Description Returns
... - T constructor parameters -

Note

BOOST_DI_INJECT_TRAITS constructor parameters is limited to BOOST_DI_CFG_CTOR_LIMIT_SIZE, which by default is set to 10.

Test CPP(SPLIT) CPP(SPLIT) Example

CPP(BTN)



--- di::inject ---

Header

#include <boost/di.hpp>

Description

di::inject informs [Boost].DI about constructor parameters. It's useful for generated/generic classes as it doesn't have constructor parameters size limitations.

Semantics

struct T {
  using boost_di_inject__ = di::inject<...>;
  T(...) {}
};
Expression Requirement Description Returns
... - T constructor parameters -

Note

di::inject has no limitations if it comes to constructor parameters, however, named parameters are not allowed. Moreover, you can replace di::inject with any variadic type list type to remove dependency to [Boost].DI. For example, template<class...> struct type_list{}; using boost_di_inject__ = type_list<...>;

Test CPP(SPLIT) CPP(SPLIT) Example

CPP(BTN)



--- di::ctor_traits ---

Header

#include <boost/di.hpp>

Description

di::ctor_traits is a trait in which constructor parameters for type T might be specified. It's useful for third party classes you don't have access to and which can't be created using automatic injection.

Semantics

namespace boost {
namespace di {
  template <>
  struct ctor_traits<T> {
    BOOST_DI_INJECT_TRAITS(...); // or using type = di::inject<...>;
  };
}}

Test CPP(SPLIT) Example

CPP(BTN)



Annotations

Annotations are type properties specified in order to refer to a type by the name instead of the type it self. They are useful when constructor has more than one parameter of the same type. For example, T(int, int).

--- (named = name) ---

Header

#include <boost/di.hpp>

Description

Named parameters are handy to distinguish different constructor parameters of the same type.

  T(int value1, int value2);

In order to inject proper values into value1 and value2 they have to be differentiate somehow. [Boost].DI solution for this problem are annotations.

Note

Annotations might be set only when constructor is marked using BOOST_DI_INJECT or BOOST_DI_INJECT_TRAITS.

Semantics

auto Name = []{}; // just an object

struct T {
  BOOST_DI_INJECT(T, (named = Name) type type_name [= default_value], ...);
};
Expression Requirement Description Returns
Name - Object representing named type -

Example

BOOST_DI_INJECT(T, (named = value_1) int value1, (named = value_2) int value2);

Note

Implementation of constructor doesn't require annotations, only constructor definition requires them.

Test CPP(SPLIT) CPP(SPLIT) CPP(SPLIT) CPP(SPLIT) Example

CPP(BTN) CPP(BTN) CPP(BTN)



Scopes

Header

#include <boost/di.hpp>

Description

Scopes are responsible for creating and maintaining life time of dependencies. If no scope will be given, deduce scope will be assumed.

Semantics

template <class TExpected, class TGiven>
struct scope {
  template <class T>
  using is_referable;

  template <class T, class TName, class TProvider>
  static auto try_create(const TProvider&);

  template <class T, class TName, class TProvider>
  auto create(const TProvider&);
};
Expression Requirement Description Returns
TExpected - 'Interface' type -
TGiven - 'Implementation' type -
is_referable<T> - Verifies whether scope value might be converted to a reference true_type/false_type
try_create<T, TName, TProvider> providable<TProvider> Verifies whether type T might be created true_type/false_type
create<T, TName, TProvider> providable<TProvider> Creates type T T
Type/Scope unique singleton instance
T -
T& -
const T& ✔ (temporary)
T* (transfer ownership) - -
const T* - -
T&& -
std::unique_ptr - -
std::shared_ptr
boost::shared_ptr - / ✔ converted to
std::weak_ptr - - / ✔ converted to

Test CPP(SPLIT) Example

CPP(BTN) CPP(BTN) CPP(BTN) CPP(BTN)





--- di::deduce (default) ---

Header

#include <boost/di.hpp>

Description

Default scope which will be converted to one of the scopes depending on the type.

Type Scope
T unique
T& singleton
const T& unique (temporary) / singleton
T* unique (ownership transfer)
const T* unique (ownership transfer)
T&& unique
std::unique_ptr unique
std::shared_ptr singleton
boost::shared_ptr singleton
std::weak_ptr singleton

Semantics

namespace scopes {
  struct deduce {
    template <class TExpected, class TGiven>
    struct scope {
      template <class T>
      using is_referable;

      template <class T, class TName, class TProvider>
      static auto try_create(const TProvider&);

      template <class T, class TName, class TProvider>
      auto create(const TProvider&);
    };
  };
}

scopes::deduce deduce;
Expression Requirement Description Returns
TExpected - 'Interface' type -
TGiven - 'Implementation' type -
is_referable<T> - Verifies whether scope value might be converted to a reference true_type/false_type
try_create<T, TName, TProvider> providable<TProvider> Verifies whether type T might be created true_type/false_type
create<T, TName, TProvider> providable<TProvider> Creates type T T

Test CPP(SPLIT) Example

CPP(BTN) CPP(BTN)



--- di::instance (di::bind<>.to(value)) ---

Header

#include <boost/di.hpp>

Description

Scope representing values - passed externally. The life time of the object depends on the user. [Boost].DI is not maintaining the life time of these objects, however, values and strings will be copied and managed by the library.

Type instance[in] (bind<>.to(in)) instance[out] (injector.create<out>())
T
T&
const T&
T* - -
const T* - -
T&&
std::unique_ptr - -
std::shared_ptr
boost::shared_ptr -
std::weak_ptr -

Semantics

namespace scopes {
  struct instance {
    template <class TExpected, class TGiven>
    struct scope {
      template <class T>
      using is_referable;

      template <class T, class TName, class TProvider>
      static auto try_create(const TProvider&);

      template <class T, class TName, class TProvider>
      auto create(const TProvider&);
    };
  };
}
Expression Requirement Description Returns
TExpected - 'Interface' type -
TGiven - 'Implementation' type -
is_referable<T> - Verifies whether scope value might be converted to a reference true_type/false_type
try_create<T, TName, TProvider> providable<TProvider> Verifies whether type T might be created true_type/false_type
create<T, TName, TProvider> providable<TProvider> Creates type T T

Test CPP(SPLIT) Example

CPP(BTN) CPP(BTN)



--- di::singleton ---

Header

#include <boost/di.hpp>

Description

Scope representing shared value between all instances as well as threads. Singleton scope will be deduced in case of reference, std::shared_ptr, boost::shared_ptr or std::weak_ptr.

Note

Singleton scope will convert automatically between std::shared_ptr and boost::shared_ptr if required.

Type singleton
T -
T&
const T&
T* -
const T* -
T&& -
std::unique_ptr -
std::shared_ptr
boost::shared_ptr
std::weak_ptr

Semantics

namespace scopes {
  struct singleton {
    template <class TExpected, class TGiven>
    struct scope {
      template <class T>
      using is_referable;

      template <class T, class TName, class TProvider>
      static auto try_create(const TProvider&);

      template <class T, class TName, class TProvider>
      auto create(const TProvider&);
    };
  };
}

scopes::singleton singleton;
Expression Requirement Description Returns
TExpected - 'Interface' type -
TGiven - 'Implementation' type -
is_referable<T> - Verifies whether scope value might be converted to a reference true_type/false_type
try_create<T, TName, TProvider> providable<TProvider> Verifies whether type T might be created true_type/false_type
create<T, TName, TProvider> providable<TProvider> Creates type T T

Test CPP(SPLIT) Example

CPP(BTN) CPP(BTN)



--- di::unique ---

Header

#include <boost/di.hpp>

Description

Scope representing unique/per request value. A new instance will be provided each time type will be requested.

Type unique
T
T& -
const T& ✔ (temporary)
T* ✔ (ownership transfer)
const T* ✔ (ownership transfer)
T&&
std::unique_ptr
std::shared_ptr
boost::shared_ptr
std::weak_ptr -

Semantics

namespace scopes {
  struct unique {
    template <class TExpected, class TGiven>
    struct scope {
      template <class T>
      using is_referable;

      template <class T, class TName, class TProvider>
      static auto try_create(const TProvider&);

      template <class T, class TName, class TProvider>
      auto create(const TProvider&);
    };
  };
}

scopes::unique unique;
Expression Requirement Description Returns
TExpected - 'Interface' type -
TGiven - 'Implementation' type -
is_referable<T> - Verifies whether scope value might be converted to a reference true_type/false_type
try_create<T, TName, TProvider> providable<TProvider> Verifies whether type T might be created true_type/false_type
create<T, TName, TProvider> providable<TProvider> Creates type T T

Test CPP(SPLIT) Example

CPP(BTN)



Modules

Header

#include <boost/di.hpp>

Description

Modules allow to split bindings configuration into smaller injectors. Module might be installed by passing it into make_injector.

Semantics

auto module = di::make_injector(...);
di::injector<Ts...> module = di::make_injector(...);
Expression Description Note
auto module = di::make_injector(...) All types are exposed from module module.create<T>() is allowed for any T
di::injector<Ts...> module = di::make_injector(...) Only Ts... types are exposed from module module.create<T>() is allowed only for T <= Ts...

Test CPP(SPLIT) CPP(SPLIT) CPP(SPLIT) Example

CPP(BTN)



--- BOOST_DI_EXPOSE ---

Header

#include <boost/di.hpp>

Description

BOOST_DI_EXPOSE is a macro definition allowing to expose named parameters via module/injector.

Semantics

di::injector<BOOST_DI_EXPOSE((named = Name) T), ...>;
Expression Requirement Description Returns
Name - Named object -
... - More types to be exposed -

Test CPP(SPLIT) CPP(SPLIT) Example

CPP(BTN)



Providers

Header

#include <boost/di.hpp>

Description

Providers are responsible for creating objects using given Configuration.

Semantics

namespace type_traits {
  struct direct; // T(...)
  struct uniform; // T{...}
  struct heap; // new T
  struct stack; // T
}

namespace providers {
  class provider {
    public:
      template <class T, class... TArgs>
      struct is_creatable;

      template <
        class T
      , class TInit // type_traits::direct/type_traits::uniform
      , class TMemory // type_traits::heap/type_traits::stack
      , class... TArgs
      > auto get(const TInit&, const TMemory&, TArgs&&... args) const;
  };
}

struct config : di::config {
  template<class TInjector>
  static auto provider(const TInjector&) noexcept { return providers::stack_over_heap{}; }
};
Expression Requirement Description Returns
TInjector - injector -
is_creatable<T, TArgs...> creatable<TArgs...> Verify whether T is creatable with TArgs... true_type/false_type
get(const TInit&, const TMemory&, TArgs&&...) TInit -> direct/uniform, TMemory -> heap/stack Creates type T with TArgs... T

Note

Provider used by injector might changed locally via make_injector or globally via BOOST_DI_CFG.

Test CPP(SPLIT) Example

CPP(BTN) CPP(BTN)



--- di::providers::stack_over_heap (default) ---

Header

#include <boost/di.hpp>

Description

Creates objects on the stack whenever possible, otherwise on the heap.

Semantics

namespace providers {
  class stack_over_heap {
    public:
      template <class T, class... TArgs>
      struct is_creatable;

      template <
        class T
      , class TInit // type_traits::direct/type_traits::uniform
      , class TMemory // type_traits::heap/type_traits::stack
      , class... TArgs
      > auto get(const TInit&, const TMemory&, TArgs&&... args) const;
  };
}
Expression Requirement Description Returns
is_creatable<T, TArgs...> creatable<TArgs...> Verify whether T is creatable with TArgs... true_type/false_type
get(const TInit&, const TMemory&, TArgs&&...) TInit -> direct/uniform, TMemory -> heap/stack Creates type T with TArgs... T
Type TMemory
T stack
T& stack
const T& stack
T&& stack
T* heap
const T* heap
std::unique_ptr heap
std::shared_ptr heap
std::weak_ptr heap
boost::shared_ptr heap
is_polymorphic<T> heap

Test CPP(SPLIT) Example

CPP(BTN) CPP(BTN)



--- di::providers::heap ---

Header

#include <boost/di.hpp>

Description

Basic provider creates objects on the heap (always).

Semantics

namespace providers {
  class heap {
    public:
      template <class T, class... TArgs>
      struct is_creatable;

      template <
        class T
      , class TInit // type_traits::direct/type_traits::uniform
      , class TMemory // type_traits::heap/type_traits::stack
      , class... TArgs
      > auto get(const TInit&, const TMemory&, TArgs&&... args) const;
  };
}
Expression Requirement Description Returns
is_creatable<T, TArgs...> creatable<TArgs...> Verify whether T is creatable with TArgs... true_type/false_type
get(const TInit&, const TMemory&, TArgs&&...) TInit -> direct/uniform, TMemory -> heap/stack Creates type T with TArgs... T

Test CPP(SPLIT) Example

CPP(BTN) CPP(BTN) CPP(BTN)





Policies

Header

#include <boost/di.hpp>

Description

Policies operates on dependencies in order to limit allowed behaviour or visit created types during run-time. Policies are set up via Configuration.

Note

By default [Boost].DI has NO policies enabled.

Semantics

template <class... TPolicies> requires callable<TPolicies...>
auto make_policies(TPolicies...) noexcept;

struct config : di::config {
  template<class TInjector>
  static auto policies(const TInjector&) noexcept { return make_policies(...); }
};                                                                        |
                                                                          |
// policy                                                                 /
template<class T>   <-----------------------------------------------------
void operator()(const T&);
Expression Requirement Description Returns
TInjector - injector -
make_policies<TPolicies...> callable<TPolicies...> Creates policies callable list
T Description Example
T::type Type to be created std::shared_ptr<int>
T::expected Decayed 'Interface' type interface
T::given Decayed 'Given' type implementatoin
T::name Annotation name my_name
T::arity Number of constructor arguments integral_constant<int, 3>
T::scope scope singleton
T::is_root Is the root object (a type create was called with) true_type/false_type

Note

In order for injector to verify policies they have to be created using config and passed via TConfig in make_injector or set it globally via BOOST_DI_CFG.

Test CPP(SPLIT) CPP(SPLIT) Example

CPP(BTN) CPP(BTN) CPP(BTN)





--- di::policies::constructible ---

Header

#include <boost/di.hpp>

Description

Constructible policy limits constructor parameters to explicitly allowed.

Note

By default constructible policy disables creation of any constructor parameters.

Semantics

namespace policies {
  struct _ { }; // placeholder

  constexpr auto include_root = true;

  template<class T>
  struct is_root; // true when is the root type (`create<RooType>()`)

  template<class T>
  struct is_bound; // true when type is bound with 'di::bind<T>'

  template <class T>
  struct is_injected; // true when type is injected using 'BOOST_DI_INJECT' or is 'fundamental'

  template<bool IncludeRoot = false, class T>
  auto constructible(const T&) noexcept;
}

namespace operators {
  template<class X>
  inline auto operator!(const X&)

  template<class X, class Y>
  inline auto operator&&(const X&, const Y&);

  template<class X, class Y>
  inline auto operator||(const X&, const Y&);
}
Expression Requirement Description Returns
is_root<T> - Verify whether type T is a root type true_type/false_type
is_bound<T> - Verify whether type T is bound true_type/false_type
is_injected<T> - Verify whether type T is injected via BOOST_DI_INJECT true_type/false_type

Note

In order to allow logic operators using namespace boost::di::policies::operators has to be used.

Test CPP(SPLIT) CPP(SPLIT)

Note

STL type traits are supported and might be combined with [Boost].DI traits in order to limit constructor types For example, std::is_same<_, int>{} || std::is_constructible<_, int, int>{} || std::is_base_of<int, _>{}, etc...

Example

CPP(BTN) CPP(BTN) CPP(BTN)





Concepts

Concepts are types constraints which ensure that only given types which are satisfied by the constraint will be allowed. If type doesn't satisfy the concept short and descriptive error message is provided.

--- di::concepts::boundable ---

Header

#include <boost/di.hpp>

Description

Bindings type requirement.

Synopsis

template <class TExpected, class TGiven>
concept bool boundable() {
  return is_complete<TExpected>()
      && is_complete<TGiven>()
      && (is_base_of<TExpected, TGiven>() || is_convertible<TGiven, TExpected>());
}

template <class... Ts>
concept bool boundable() {
  return is_supported<Ts>()...
      && is_movable<Ts>()...
      && (is_base_of<injector, Ts>()... || is_base_of<dependency, Ts>()...);
}

Semantics

boundable<T>
boundable<Ts...>
Expression Description Returns
Ts... Bindings to be verified true_type if constraint is satisfied, Error otherwise

Example

Error type<T>::has_disallowed_qualifiers
Description type T has disallowed qualifiers
Expression CPP
Error type<T>::is_abstract
Description type T is abstract
BOOST_DI_CFG_DIAGNOSTICS_LEVEL 0, 1 -> no additional info, 2 -> info about why type T is abstract
Expression CPP
Error type<T>::is_not_related_to
Description type T is not related to type U
Expression CPP
Error type<T>::is_bound_more_than_once
Description type T is bound more than once
Expression CPP
Error type<T>::is_neither_a_dependency_nor_an_injector
Description type T is neither a dependency nor an injector
Expression CPP

--- di::concepts::callable ---

Header

#include <boost/di.hpp>

Description

Policy type requirement.

Synopsis

template <class T>
concept bool callable() {
  return requires(T object) {
    { object(...) };
  }
}

Semantics

callable<T>

Example

Error policy<TPolicy>::requires_<call_operator>
Description policy TPolicy requires a call operator
Expression CPP

--- di::concepts::configurable ---

Header

#include <boost/di.hpp>

Description

Configuration type requirement.

Synopsis

template <class T>
concept bool configurable() {
  return requires(T object) {
    return providable<decltype(T::provider(...))> && callable<decltype(T::policies(...))>();
  }
}

Semantics

configurable<T>

Example

Error config<TConfig>::requires_<provider<providable_type (...)>>
Description config T requires only providable and callable types
Expression CPP

--- di::concepts::creatable ---

Header

#include <boost/di.hpp>

Description

Requirement for type T which is going to be created via injector.create<T>()

Synopsis

namespace type_traits {
  template<class T>
  using ctor_traits; // returns list of constructor parameters
}

template <class T, class... TArgs>
concept bool creatable() {
  return is_constructible<T, TArgs...>() &&
         is_constructible<TArgs, type_traits::ctor_traits<TArgs>...>();
}

Semantics

creatable<T, TArgs...>

Example

Error abstract_type<T>::is_not_bound
Description abstract type T is not bound
BOOST_DI_CFG_DIAGNOSTICS_LEVEL 0 -> 'constraint not satisfied', 1 -> (0) + abstract type is not bound, 2 -> (1) + creation tree
Suggestion 'type is not bound, did you forget to add: 'di::bind.to()'?'
Expression CPP
Expression CPP
Error type<T>::has_ambiguous_number_of_constructor_parameters::given<Given>::expected<Expected>
Description type T has ambiguous number of constructor parameters where Given were provided but Expected were expected
BOOST_DI_CFG_DIAGNOSTICS_LEVEL 0 -> 'constraint not satisfied', 1 -> (0) + abstract type is not bound, 2 -> (1) + creation tree
Suggestion 'verify BOOST_DI_INJECT_TRAITS or di::ctor_traits'
Expression CPP
Error type<T>::has_to_many_constructor_parameters::max<Max>
Description type T has to many constructor parameter where maximum number is Max
BOOST_DI_CFG_DIAGNOSTICS_LEVEL 0 -> 'constraint not satisfied', 1 -> (0) + abstract type is not bound, 2 -> (1) + creation tree
Suggestion 'increase BOOST_DI_CFG_CTOR_LIMIT_SIZE value or reduce number of constructor parameters'
Expression CPP
Error scoped<TScope>::is_not_convertible_to<T>
Description scope TScope is not convertible to type T
BOOST_DI_CFG_DIAGNOSTICS_LEVEL 0 -> 'constraint not satisfied', 1 -> (0) + abstract type is not bound, 2 -> (1) + creation tree
Suggestion 'scoped object is not convertible to the requested type, did you mistake the scope: 'di::bind.in(scope)'?'
Expression CPP
Error scoped<instance>::is_not_convertible_to<T>
Description instance is not convertible to type T
BOOST_DI_CFG_DIAGNOSTICS_LEVEL 0 -> 'constraint not satisfied', 1 -> (0) + abstract type is not bound, 2 -> (1) + creation tree
Suggestion 'instance is not convertible to the requested type, verify binding: 'di::bind.to(value)'?'
Expression CPP

Note

Suggestions are not supported/displayed by MSVC-2015.


--- di::concepts::providable ---

Header

#include <boost/di.hpp>

Description

Provider type requirement.

Synopsis

namespace type_traits {
  struct direct;
  struct uniform;
  struct stack;
  struct heap;
}

template <class T>
concept bool providable() {
  return requires(T object) {
    { object.template get<_>(type_traits::direct/type_traits::uniform{}, type_traits::stack/type_traits::heap{}, ...) };
    { object.template is_creatable<_>(type_traits::direct/type_traits::uniform{}, type_traits::stack/type_traits::heap{}, ...) };
  }
}

Semantics

providable<T>

Example

Error provider<TProvider>::requires_<get>
Description provider TProvider requires get method
Expression CPP

--- di::concepts::scopable ---

Header

#include <boost/di.hpp>

Description

Scope type requirement.

Synopsis

struct _ {}; // any type

template <class T>
concept bool scopable() {
  return requires(T) {
    typename scope<_, _>::is_referable;
    { T::scope<_, _>{}.try_create() };
    { T::scope<_, _>{}.create() };
  }
}

Semantics

scopable<T>

Example

Error scope<TScope>::requires_<create>
Description scope TScope requires create method
Expression CPP

Configuration

--- di::config ---

Header

#include <boost/di.hpp>

Description

Injector configuration.

Synopsis

struct config {
  static auto provider(...) noexcept;
  static auto policies(...) noexcept;
};
Expression Requirement Description Returns
provider() providable Creates provider providable
policies() callable Creates policies callable
Expression Description
BOOST_DI_CFG Global configuration allows to customize provider and policies

Semantics

di::make_injector<config>(...)
// or
#define BOOST_DI_CFG config // change default
di::make_injector(...)

Test CPP(SPLIT) Example

CPP(BTN) CPP(BTN) CPP(BTN)