Home

Awesome

<a href="http://www.boost.org/LICENSE_1_0.txt" target="_blank">Boost Licence</a> <a href="https://github.com/boost-ext/di/releases" target="_blank">Version</a> <a href="https://github.com/boost-ext/di/actions/workflows/build.yml" target="_blank">Linux</a> <a href="https://codecov.io/gh/boost-ext/di" target="_blank">Coveralls</a> <a href="http://github.com/boost-ext/di/issues" target="_blank">Github Issues</a> <a href="https://godbolt.org/z/5qTKhf">Try it online</a>


[Boost::ext].DI

Your C++14 one header only Dependency Injection library with no dependencies

<p align="center"><a href="https://www.youtube.com/watch?v=yVogS4NbL6U"><img src="doc/images/di_concept.png" alt="Dependency Injection"/></a></p>

https://www.youtube.com/watch?v=yVogS4NbL6U


Quick start

Download

[Boost::ext].DI requires only one file. Get the latest header here!

Include

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

Compile

Quick guide - Create object graph

class ctor {
public:
  explicit ctor(int i) : i(i) {}
  int i;
};

struct aggregate {
  double d;
};

class example {
 public:
  example(aggregate a, const ctor& c) {
    assert(87.0 == a.d);
    assert(42 == c.i);
  };
};

int main() {
  const auto injector = di::make_injector(
    di::bind<int>.to(42),
    di::bind<double>.to(87.0)
  );

  injector.create<example>();
}

Run this example on Wandbox.

<p align="center"> <table> <tr> <th></th> <th>Clang-3.8</th> <th>GCC-6</th> <th>MSVC-2015</th> </tr> <tr> <td>Compilation Time</td> <td>0.102s</td> <td>0.118s</td> <td>0.296s</td> </tr> <tr> <td>Binary size (stripped)</td> <td>6.2kb</td> <td>6.2kb</td> <td>105kb</td> </tr> <tr> <td>ASM x86-64</td> <td colspan="3"> <pre><code> xor eax, eax retq </code></pre> </td> </tr> </table> </p>

Quick guide - Bind interfaces

struct interface {
  virtual ~interface() noexcept = default;
  virtual int get() const = 0;
};

class implementation : public interface {
public:
  int get() const override { return 42; }
};

struct example {
  example(std::shared_ptr<interface> i) {
    assert(42 == i->get());
  }
};

int main() {
  const auto injector = di::make_injector(
    di::bind<interface>.to<implementation>()
  );

  injector.create<std::unique_ptr<example>>();
}

Run this example on Wandbox.

<p align="center"> <table> <tr> <th></th> <th>Clang-3.8</th> <th>GCC-6</th> <th>MSVC-2015</th> </tr> <tr> <td>Compilation Time</td> <td>0.102s</td> <td>0.118s</td> <td>0.296s</td> </tr> <tr> <td>Binary size (stripped)</td> <td>6.2kb</td> <td>6.2kb</td> <td>105kb</td> </tr> <tr> <td>ASM x86-64 (same as `make_unique<example>`)</td> <td colspan="3"> <pre><code> push %rbx mov %rdi,%rbx mov $0x8,%edi callq 0x4008e0 <_Znwm@plt> movq $0x400c78,(%rax) mov %rax,(%rbx) mov %rbx,%rax pop %rbx retq </code></pre> </td> </tr> </table> </p>

Quick guide - Bind templates

template<class ErrorPolicy = class TErrorPolicy>
class simple_updater {
public:
  void update() const {
    ErrorPolicy::on("update");
  }
};

template<class Updater = class TUpdater>
class example {
public:
  explicit example(const Updater& updater)
    : updater(updater)
  { }

  void update() {
    updater.update();
  }

private:
  const Updater& updater;
};

int main() {
  struct throw_policy {
    static void on(const std::string& str) {
      throw std::runtime_error(str);
    }
  };

  const auto injector = di::make_injector(
    di::bind<class TErrorPolicy>.to<throw_policy>(),
    di::bind<class TUpdater>.to<simple_updater>()
  );

  injector.create<example>().update();
  // Terminates with an uncaught exception because of our bound error policy
}

Run this example on Wandbox.

<p align="center"> <table> <tr> <th></th> <th>Clang-3.8</th> <th>GCC-6</th> <th>MSVC-2015</th> </tr> <tr> <td>Compilation Time</td> <td>0.102s</td> <td>0.118s</td> <td>0.296s</td> </tr> <tr> <td>Binary size (stripped)</td> <td>6.2kb</td> <td>6.2kb</td> <td>105kb</td> </tr> <tr> <td>ASM x86-64</td> <td colspan="3"> <pre><code> xor eax, eax retq </code></pre> </td> </tr> </table> </p>

Quick guide - Bind concepts

struct Streamable {
 template<class T>
 auto requires(T&& t) -> decltype(
   int( t.read() ),
   t.write(int)
 );
};

template<class Exchange = Streamable(class ExchangeStream)
         class Engine   = Streamable(class EngineStream)>
class example {
public:
  example(Exchange exchange, Engine engine)
    : exchange(std::move(exchange)), engine(std::move(engine))
  { }
  
private:
  Exchange exchange;
  Engine engine;
};

int main() {
  const auto injector = di::make_injector(
    di::bind<Streamable(class ExchangeStream)>.to<exchange>(),
    di::bind<Streamable(class EngineStream)>.to<engine>()
  );

  injector.create<example>();
}

Run this example on Wandbox.

<p align="center"> <table> <tr> <th></th> <th>Clang-3.8</th> <th>GCC-6</th> <th>MSVC-2015</th> </tr> <tr> <td>Compilation Time</td> <td>0.102s</td> <td>0.118s</td> <td>0.296s</td> </tr> <tr> <td>Binary size (stripped)</td> <td>6.2kb</td> <td>6.2kb</td> <td>105kb</td> </tr> <tr> <td>ASM x86-64</td> <td colspan="3"> <pre><code> xor eax, eax retq </code></pre> </td> </tr> </table> </p>

Documentation


Disclaimer [Boost::ext].DI is not an official Boost library.