#include <iostream>
#include <string>
#include <boost/shared_ptr.hpp>
#include <boost/format.hpp>
#include "di/constructor.hpp"
class IQuoteService
{
public:
virtual ~IQuoteService(){};
virtual std::string quote() = 0;
};
template<int N>
class SameQuoteService : public IQuoteService
{
public:
explicit
SameQuoteService(std::string const & quote):
m_quote((boost::format("%1% %2%") % N % quote).str())
{}
virtual
std::string
quote()
{ return m_quote; }
private:
std::string m_quote;
};
struct SameQuoteTag
{};
struct NoArgConstructor
{
NoArgConstructor()
{ variable = 5; }
int variable;
};
#define REQUIRE(expr) \
if(!(expr)) std::cout << #expr " failed!"; \
else (void)0
class Application
{
public:
Application(boost::shared_ptr<IQuoteService> q0,
boost::shared_ptr<IQuoteService> q1,
boost::shared_ptr<IQuoteService> q2,
boost::shared_ptr<IQuoteService> q3):
m_q0(q0),
m_q1(q1),
m_q2(q2),
m_q3(q3)
{}
void
exec()
{
for(std::size_t ii = 0; ii < 3; ++ii)
{
std::cout << "quote[" << ii << "]: " << m_q0->quote() << std::endl;
std::cout << "quote[" << ii << "]: " << m_q1->quote() << std::endl;
std::cout << "quote[" << ii << "]: " << m_q2->quote() << std::endl;
std::cout << "quote[" << ii << "]: " << m_q3->quote() << std::endl;
}
}
private:
boost::shared_ptr<IQuoteService> m_q0,m_q1,m_q2,m_q3;
};
int main()
{
try
{
ObjectConstructor c;
// Register a type which has a no argument constructor
c.registerType<NoArgConstructor>();
// Register a type and mark one of its arguments as bound. This is
// more convenient than creating a new type for simple or
// value-based arguments.
c.registerType<SameQuoteService<1>,void(Bind<
SameQuoteTag,
std::string const &> )>();
c.registerType<SameQuoteService<2>,void(Bind<
SameQuoteTag,
std::string const &> )>();
c.registerType<SameQuoteService<3>,void(Bind<
SameQuoteTag,
std::string const &> )>();
c.registerType<SameQuoteService<4>,void(Bind<
SameQuoteTag,
std::string const &> )>();
// Bind arguments. This means that any arguments or types that are
// bound with these parameters will produce the value "Hi". Note
// that the type of the bound value does not need to match
// exactly, just be copyable and convertible to the target.
c.bindValue<Bind<SameQuoteTag,std::string const &> >("Hi");
// Register the "root" application object which requires a
// SameQuoteService. Note that the actual constructor requires an
// IQuoteService. Eventually this will be separate from type
// registration (that is, the registration signature will match
// the constructor exactly.) This is desirable in order to allow
// for interface-based programming.
c.registerType<Application,void(boost::shared_ptr<SameQuoteService<1> >,
boost::shared_ptr<SameQuoteService<2> >,
boost::shared_ptr<SameQuoteService<3> >,
boost::shared_ptr<SameQuoteService<4> >)>();
REQUIRE(c.constructType<NoArgConstructor>().variable == 5);
REQUIRE((c.constructType<Bind<SameQuoteTag,std::string const&> >()
== "Hi"));
REQUIRE(c.constructType<boost::shared_ptr<SameQuoteService<1> > >()->quote()
== "1 Hi");
// Construct root object. Note that no arguments needed to be
// passed, the library figured everything out
boost::shared_ptr<Application> app =
c.constructType<boost::shared_ptr<Application> >();
app->exec();
/**
Output:
quote[0]: 1 Hi
quote[0]: 2 Hi
quote[0]: 3 Hi
quote[0]: 4 Hi
quote[1]: 1 Hi
quote[1]: 2 Hi
quote[1]: 3 Hi
quote[1]: 4 Hi
quote[2]: 1 Hi
quote[2]: 2 Hi
quote[2]: 3 Hi
quote[2]: 4 Hi
**/
return 0;
}
catch(std::exception const & e)
{
std::cout << "*********EXCEPTION*********" << std::endl
<< e.what() << std::endl;
return 1;
}
}