This is a header-only library with some of the most common design patterns implemmented in C 11/14.
- Can assume variadic templates supported by your compiler.
- Use perfect forwarding and new features from C 11/14 when possible.
- Prefer header only code, but it is not a must.
- Allocations and deallocations of memory are centralized in a allocator selectable by client. (TODO: now allocator is FSBAllocator, and require some change.)
- Code tested in travis on gcc (4.7, 4.8, 4.9), clang (3.3, 3.4 and 3.6) and Visual Studio (2013).
- Test cases relationated with problems crossing boundaries of dynamic libraries.
- Side dark is optional (no macros, no singletons).
design-patterns-cpp14 by Ricardo Marmolejo García is licensed under a Creative Commons Reconocimiento 4.0 Internacional License.
The source for design-patterns-cpp14 is held at design-patterns-cpp14 github.com site.
To report an issue, use the design-patterns-cpp14 issue tracker at github.com.
It's a header-only library. Only need an include.
You will need cmake, npm and conan (and a compiler).
$ git clone https://github.com/makiolo/design-patterns-cpp14.git
$ cd design-patterns-cpp14
$ npm install
- option 1: use DEFINE_KEY(classname or anything) within the class
- option 2: use DEFINE_HASH(classname well qualified) outside of class
- option 3: specialization of std::hash. This is equivalent to option 2 but without use macros:
namespace std {
template <>
struct hash<MyClass>
{
size_t operator()() const
{
return std::hash<std::string>()("MyClass");
}
};
}
#include <iostream>
#include <assert.h>
#include <dp14/factory.h>
class Base
{
public:
using factory = dp14::factory<Base, std::string, int>;
explicit Base(const std::string& name, int q)
: _name(name)
, _q(q)
{
std::cout << "constructor " << _name << " - " << _q << std::endl;
}
virtual ~Base() { std::cout << "destruction" << std::endl; }
protected:
std::string _name;
int _q;
};
class A : public Base
{
public:
DEFINE_KEY(A)
explicit A(const std::string& name, int q) : Base(name, q) { ; }
virtual ~A() = default;
};
DEFINE_HASH(A)
// if you dont like macro DEFINE_KEY(class), can use this:
class B : public Base
{
public:
explicit B(const std::string& name, int q) : Base(name, q) { ; }
virtual ~B() = default;
};
namespace std {
template <>
struct hash<B>
{
size_t operator()() const
{
return std::hash<std::string>()("B");
}
};
}
int main()
{
Base::factory factory;
Base::factory::registrator<A> reg1(factory);
Base::factory::registrator<B> reg2(factory);
{
// equivalent ways of create A
std::shared_ptr<Base> a1 = factory.create<A>("first parameter", 2);
std::shared_ptr<A> a2 = factory.create<A>("first parameter", 2);
std::shared_ptr<Base> a3 = factory.create("A", "first parameter", 2);
// equivalent ways of create B
std::shared_ptr<Base> b1 = factory.create<B>("first parameter", 2);
std::shared_ptr<B> b2 = factory.create<B>("first parameter", 2);
std::shared_ptr<Base> b3 = factory.create("B", "first parameter", 2);
assert(a1 != a2);
assert(a3 != b1);
assert(b1 != b2);
}
return(0);
}
#include <iostream>
#include <sstream>
#include <assert.h>
#include <dp14/memoize.h>
class Base
{
public:
using memoize = dp14::memoize<Base, std::string, int>;
explicit Base(const std::string& name, int q)
: _name(name)
, _q(q)
{
std::cout << "constructor " << _name << " - " << _q << std::endl;
}
virtual ~Base() { std::cout << "destruction" << std::endl; }
protected:
std::string _name;
int _q;
};
class A : public Base
{
public:
DEFINE_KEY(A)
explicit A(const std::string& name, int q) : Base(name, q) { ; }
virtual ~A() = default;
};
class B : public Base
{
public:
DEFINE_KEY(B)
explicit B(const std::string& name, int q) : Base(name, q) { ; }
virtual ~B() = default;
};
int main()
{
Base::memoize m;
Base::memoize::registrator<A> reg1(m);
Base::memoize::registrator<B> reg2(m);
{
std::shared_ptr<Base> a1 = m.get<A>("first parameter", 2);
assert( m.exists<A>("first parameter", 2) == true );
}
assert( m.exists<A>("first parameter", 2) == false );
{
std::shared_ptr<Base> a1 = m.get<A>("first parameter", 2);
std::shared_ptr<A> a2 = m.get<A>("first parameter", 2);
assert(a1 == a2);
std::shared_ptr<Base> a3 = m.get("A", "first parameter", 4);
assert(a2 != a3);
std::shared_ptr<Base> b1 = m.get<B>("first parameter", 2);
std::shared_ptr<B> b2 = m.get<B>("first parameter", 2);
assert(b1 == b2);
std::shared_ptr<Base> b3 = m.get("B", "first parameter", 4);
assert(b2 != b3);
assert( m.exists<A>("first parameter", 2) == true );
}
assert( m.exists<A>("first parameter", 2) == false );
return(0);
}