for unit testing, I'm trying to create a Factory which meets the following requirements:
(1) It can create arbitrary objects (e.g. Timer and TimerMock)
(2) It returns unique_ptrs to a Base class to these objects (e.g. unique_ptr<TimerInterface>)
(3) The Factory itself can be passed around as a base class pointer too
(4) It shall be possible to call any constructor to create the Object [edit1]using the same factory object[/edit1]
The purpose is to do dependency injection with this factories to be able to exchange objects that are not part of the test with mock objects.
Here's what I have so far:
#include <memory>
#include <iostream>
//"perfect factory method"
//usage: std::unique_ptr<Type> pt(create<Type>(Type-constructor-arguments));
template <typename Type, typename ... ConstructorArgs>
auto create(ConstructorArgs&& ... args){
return std::make_unique<Type>(std::forward<ConstructorArgs>(args)...);
}
//Abstract Factory Base class
template<typename BaseType, typename ... ConstructorArgs>
class IFactory {
public:
virtual ~IFactory() = default;
virtual std::unique_ptr<BaseType> create(ConstructorArgs&& ... args) const = 0;
};
//Abstract Factory class
template <typename BaseType, typename DerivedType, typename ... ConstructorArgs>
class CFactory : public IFactory<BaseType, ConstructorArgs...>
{
public:
using Base = IFactory<BaseType, ConstructorArgs...>;
std::unique_ptr<BaseType> create(ConstructorArgs&& ... args) const override
{
return ::create<DerivedType>(std::forward<ConstructorArgs>(args)...);
}
};
How the real Factory classes are defined:
class TimerInterface {
public:
TimerInterface() = default;
TimerInterface (const char* name);
virtual void whoami() const = 0;
/*...*/
};
class Timer: public TimerInterface {
public:
Timer() = default;
Timer(const char* name) : TimerInterface (name) {}
void whoami() const override { std::cerr << "I'm real!" << std::endl; }
/*...*/
};
class TimerMock : public TimerInterface {
public:
TimerMock () = default;
TimerMock (const char* name) : TimerInterface (name) {}
void whoami() const override { std::cerr << "I fake it!" << std::endl; }
/*...*/
};
using TimerFactory = CFactory<TimerInterface, Timer, const char*>;
using TimerMockFactory = CFactory<TimerInterface, TimerMock, const char*>;
using TimerFactoryInterface = TimerFactory::Base;
And how they are intended to be used:
class ClassUnderTest {
public:
std::unique_ptr<TimerInterface> timer {};
std::unique_ptr<TimerInterface> timer2 {};
ClassUnderTest(const TimerFactoryInterface& factory)
: timer(factory.create("I got a name!"))
//, timer2(factory.create())
{}
};
class Production
{
public:
ClassUnderTest realUsage;
Production() :
realUsage(TimerFactory())
{}
};
class Test
{
public:
ClassUnderTest tested;
Test() :
tested(TimerMockFactory())
{}
};
int main()
{
Production p;
p.realUsage.timer->whoami();
Test t;
t.tested.timer->whoami();
}
My big problem is requirement (4)
ClassUnderTest::timer2 can't be created with the same factory that's used for ClassUnderTest::timer, beause the constructor signatur already needs to be known when defining the CFactory class.
Anyone got an idea?
P.S.: "It can't be done" with an explanation is also an acceptable answer, but not my favourite ;)
Not sure if it helps, but TimerInterface doesn't need to be a complete type when you declare your two std::unique_ptr<TimerInterface> inside ClassUnderTest. Meaning this is legal:
// classundertest.hpp
// A forward-declaration is enough
class TimerInterface;
class TimerFactoryInterface;
class ClassUnderTest {
public:
std::unique_ptr<TimerInterface> timer {};
std::unique_ptr<TimerInterface> timer2 {};
// Both MUST be declared here AND defined in the .cpp for this trick to work
ClassUnderTest(const TimerFactoryInterface& factory);
~ClassUnderTest();
// classundertest.cpp
#include "classundertest.hpp"
// TimerInterface wasn't truly declared until now
#include "TimerInterface.hpp"
ClassUnderTest::ClassUnderTest(const TimerFactoryInterface& factory)
: timer(factory.create("I got a name!"))
, timer2(factory.create("???"))
{}
ClassUnderTest::~ClassUnderTest()
{}
That's basically how unique_ptr-based pimpl work.
You can do it with a std::vector<std::any>, and some index sequences, but it isn't going to be the most pretty or fast solution.
Your factory would be:
template<typename Base>
class IFactory
{
public:
virtual std::unique_ptr<Base> Create(const std::vector<std::any>& args) const = 0;
};
Your concrete factory could then be:
template<typename Base, typename Derived, typename... Args>
class CFactory : IFactory<Base>
{
private:
template<size_t... Indices>
std::unique_ptr<Base> Make(const std::vector<std::any>& args, std::index_sequence<Indices...>) const
{
return std::make_unique<Derived>(std::any_cast<Args>(args[Indices])...);
}
public:
virtual std::unique_ptr<Base> Create(const std::vector<std::any>& args) const
{
return Make(args, std::make_index_sequence<sizeof...(Args)>());
}
};
The only problem here is that you obviously cannot perfectly forward any arguments, you will always end up taking a copy.
It will also throw an std::bad_any_cast if the types passed into the std::any do not match the template.
Here's a simple test I made, and it compiles with both MSVC and Clang with -std=c++17 set:
class A
{
public:
A(int a, int b)
: Val1(a), Val2(b)
{}
A(int a)
: Val1(a), Val2(0)
{}
int Val1, Val2;
};
int main()
{
CFactory<A, A, int> fac1;
CFactory<A, A, int, int> fac2;
auto a1 = fac1.Create({ std::any(10) });
auto a2 = fac2.Create({ std::any(10), std::any(20) });
std::cout << a1->Val1 << " " << a1->Val2 << "\n";
std::cout << a2->Val1 << " " << a2->Val2 << "\n";
}
Edit: This will work for overloaded constructors, as well as any type because its template magic.
#SparkyPotato gave me the idea when stating I'd "have to manually list out the possible constructors and generate overloads for create". I just disliked the manually, so I did it by template meta programming. Thanks for the hint!
#include <memory>
#include <iostream>
#include <tuple>
//"perfect factory method"
//usage: std::unique_ptr<Type> pt(create<Type>(Type-constructor-arguments));
template <typename Type, typename ... ConstructorArgs>
auto create(ConstructorArgs&& ... args){
std::cerr << "calling " << __PRETTY_FUNCTION__ << std::endl;
return std::make_unique<Type>(std::forward<ConstructorArgs>(args)...);
}
//Abstract Factory Variadic class. This is also generic case that ends recursion
template <typename BaseType, typename TupleListOfConstructorArgs>
class IFactory
{
static_assert(std::is_same<TupleListOfConstructorArgs, std::tuple<>>::value, "");
public:
//this method shall never be instatiated, it just exists to satisfy the "using BaseFactory::create" in IFactory
template <typename T> void create(){ static_assert(sizeof(BaseType) + sizeof(T) < 0, ""); }
virtual ~IFactory() = default;
};
//Abstract Factory Variadic class specialization to perform inheritance recursion
template <typename BaseType, typename ... CurrentTupleArgs, typename ... TupleListOfConstructorArgs>
class IFactory<BaseType, std::tuple<std::tuple<CurrentTupleArgs...>, TupleListOfConstructorArgs...>> : public IFactory<BaseType, std::tuple<TupleListOfConstructorArgs...>>
{
public:
using BaseFactory = IFactory<BaseType, std::tuple<TupleListOfConstructorArgs...>>;
using BaseFactory::create;
virtual std::unique_ptr<BaseType> create(const CurrentTupleArgs& ... args) const = 0;
};
//Concrete Factory Variadic class. This is also generic case that ends inheritance recursion
template <typename BaseType, typename DerivedType, typename TupleListOfConstructorArgs, typename FullTupleListOfConstructorArgs>
class CFactory : public IFactory<BaseType, FullTupleListOfConstructorArgs>
{
static_assert(std::is_same<TupleListOfConstructorArgs, std::tuple<>>::value, "");
public:
using Base = IFactory<BaseType, FullTupleListOfConstructorArgs>;
};
//Concrete Factory Variadic class specialization to perform inheritance recursion
template <typename BaseType, typename DerivedType, typename ... CurrentTupleArgs, typename ... TupleListOfConstructorArgs, typename FullTupleListOfConstructorArgs>
class CFactory<BaseType, DerivedType, std::tuple<std::tuple<CurrentTupleArgs...>, TupleListOfConstructorArgs...>, FullTupleListOfConstructorArgs> : public CFactory<BaseType, DerivedType, std::tuple<TupleListOfConstructorArgs...>, FullTupleListOfConstructorArgs>
{
public:
using BaseFactory = CFactory<BaseType, DerivedType, std::tuple<TupleListOfConstructorArgs...>, FullTupleListOfConstructorArgs>;
using BaseFactory::create;
std::unique_ptr<BaseType> create(const CurrentTupleArgs& ... args) const override
{
std::cerr << "calling " << __PRETTY_FUNCTION__ << std::endl;
return ::create<DerivedType>(args...);
}
};
template <typename BaseType, typename DerivedType, typename TupleListOfConstructorArgs>
using CFactoryFrontend = CFactory<BaseType, DerivedType, TupleListOfConstructorArgs, TupleListOfConstructorArgs>;
class TimerInterface {
public:
TimerInterface() = default;
virtual ~TimerInterface() = default;
TimerInterface (const char* name) {}
TimerInterface(int& x, const char* name) { std::cerr << "calling " << __PRETTY_FUNCTION__ << std::endl; }
TimerInterface(const int& x, const char* name) { std::cerr << "calling " << __PRETTY_FUNCTION__ << std::endl; }
virtual void whoami() const = 0;
/*...*/
};
class Timer: public TimerInterface {
public:
Timer() = default;
Timer(const char* name) : TimerInterface (name) {}
Timer(int& x, const char* name) : TimerInterface(x, name) {}
Timer(const int& x, const char* name) : TimerInterface(x, name) {}
void whoami() const override { std::cerr << "I'm real!" << std::endl; }
/*...*/
};
class TimerMock : public TimerInterface {
public:
TimerMock () = default;
TimerMock (const char* name) : TimerInterface (name) {}
TimerMock (int& x, const char* name) : TimerInterface(x, name) {}
TimerMock (const int& x, const char* name) : TimerInterface(x, name) {}
void whoami() const override { std::cerr << "I fake it!" << std::endl; }
/*...*/
};
//using TimerInterfaceConstructors = std::tuple<std::tuple<>, std::tuple<const char*>>;
using Constructors = std::tuple<std::tuple<>, std::tuple<const char*>, std::tuple<int&, const char*>, std::tuple<const int&, const char*>>;
using TestFactory = CFactoryFrontend<TimerInterface, Timer, Constructors>;
using TimerFactory = CFactoryFrontend<TimerInterface, Timer, Constructors>;
using TimerMockFactory = CFactoryFrontend<TimerInterface, TimerMock, Constructors>;
using TimerFactoryInterface = TimerFactory::Base;
class ClassUnderTest {
public:
std::unique_ptr<TimerInterface> timer {};
std::unique_ptr<TimerInterface> timer2 {};
ClassUnderTest(const TimerFactoryInterface& factory)
: timer(factory.create("I got a name!"))
, timer2(factory.create())
{}
};
class Production
{
public:
ClassUnderTest realUsage;
Production() :
realUsage(TimerFactory())
{}
};
class Test
{
public:
ClassUnderTest tested;
Test() :
tested(TimerMockFactory())
{}
};
int main()
{
Production p;
p.realUsage.timer->whoami();
Test t;
t.tested.timer->whoami();
TestFactory tf;
TimerFactoryInterface& tfi(tf);
const char* x = "X";
tfi.create();
tfi.create(x);
int y;
const int cy = 17;
tfi.create(y, x);
tfi.create(cy, "name");
::create<Timer>(x);
}
It compiles using GCC-6 and newer and clang with -std=c++-14
class Base { ... };
class Derived1 : Base { ... };
class Derived2 : Base { ... };
template <> class BaseDecorator<Base> : **SpecificDerived** { ... };
Is it possible for SpecificDerived to reference the particular Derived class that is being used? Such that
BaseDecorator<Derived1> bd-d1;
Would instantiate a BaseDecorator that inherits from Derived1?
The problem has come about because I need to provide a decorator for a library class and all its derivations, but want to keep the code as dry as possible.
Thanks!
If I understood your question correctly, you want your BaseDecorator to inherit from specific Derived class.
If that is the case, You may do something like this:
#include <iostream>
#include <type_traits>
class Base {
public:
virtual void f1() {
std::cout << "Base::f1" << std::endl;
}
};
class Derived1 : public Base {
public:
void f1() override {
std::cout << "Derived1::f1" << std::endl;
}
};
class Derived2 : public Base {
public:
void f1() override {
std::cout << "Derived2::f1" << std::endl;
}
};
class Derived3 {
public:
void f1() {
std::cout << "Derived3::f1" << std::endl;
}
};
template <typename T,
typename = typename std::enable_if<std::is_base_of<Base, T>::value>::type >
class BaseDecorator;
template <typename T>
class BaseDecorator<T>: public T {
public:
void f2() {
T::f1();
}
};
int main() {
BaseDecorator<Derived1> bd1;
bd1.f2();
BaseDecorator<Derived2> bd2;
bd2.f2();
//BaseDecorator<Derived3> bd3; // Compilation fails !!!
//bd3.f2(); // Compilation fails !!!
return 0;
}
Output:
Derived1::f1
Derived1::f2
Suppose we have the following sample classes:
class A {
public:
explicit A(int foo) { }
void test() {
cout << "I'm in A" << endl;
}
};
class B {
public:
explicit B(string bar) { }
void test() {
cout << "I'm in B" << endl;
}
};
I would like to define a child class to inherit from a templatized class that
could be specialized as one of either A or B. The problem I'm facing is that A
and B have different constructor arguments, so building Child's constructor is
proving to be a bit vexing. Things work if I do something like the following:
template <class ParentClass>
class Child : public ParentClass {
public:
Child<B>() : ParentClass("foo") {
}
};
int main() {
Child<B> c;
c.test();
return 0;
}
However, I'd like to also be able to do something like Child<A> c. Is this
possible?
Thanks!
You may specialize for each class:
template <class ParentClass>
class Child : public ParentClass {
public:
Child();
};
template <>
Child<A>::Child() : A(42) {}
template <>
Child<B>::Child() : B("42") {}
Demo
You can try a templated constructor as follows:
#include <iostream>
using namespace std;
class A {
public:
explicit A(int foo) { }
void test() {
cout << "I'm in A" << endl;
}
};
class B {
public:
explicit B(string bar) { }
void test() {
cout << "I'm in B" << endl;
}
};
template <class Parent>
class Child
: public Parent {
public:
template <class... Args>
Child(Args... args)
: Parent(args...) {
}
};
int main() {
Child<A> a_child(42);
Child<B> b_child("42");
a_child.test();
b_child.test();
}
You can use a delegating constructor if you want to let the user decides the parameters:
template <class ParentClass>
class Child : public ParentClass {
public:
using ParentClass::ParentClass;
};
What I mean is modifying the following code, X declaration to be exact, so that I can use an object B of any kind, B<int>, B<real> ... Sadly, it's important I have an Obj<T> *pobj in B.
template <typename T>
class Obj
{
public:
T a;
public:
Obj(T a_) : a(a_) {}
void print() const
{ std::cout << "a : " << a << std::endl; }
};
template <typename T>
class A
{
public:
Obj<T> *pObj;
public:
A(Obj<T>* pO) : pObj(pO) {}
void doSomethingWithObj()
{ pObj->print(); }
static Obj<double> X;
};
Obj<double> X = Obj<double>(1.0);
template <typename T>
class B : public A<T>
{
public:
B() : A<T>( &X ) {}
void doSmthg()
{ X.print(); }
};
// in main
B<int> b;
b.doSmthg();
That code will return no known conversion for argument 1 from ‘Obj<double>*’ to ‘Obj<int>*’
You might approach it like this:
struct ObjBase
{
virtual void print() const = 0;
};
template <typename T>
class Obj : public ObjBase
{
public:
T a;
public:
Obj(T a_) : a(a_) {}
virtual void print() const
{ std::cout << "a : " << a << std::endl; }
};
template <typename T>
class A
{
public:
ObjBase *pObj;
public:
A(ObjBase* pO) : pObj(pO) {}
void doSomethingWithObj()
{ pObj->print(); }
static Obj<double> X;
};
That is, have a base class that provides an interface for the things that you want to do that are not dependent on the particular type.
Answering myself.
It is ... I forgot the qualification in my tests..
template <typename T>
class A
{
public:
Obj<T> *pObj;
public:
A(Obj<T>* pO) : pObj(pO) {}
void doSomethingWithObj()
{ pObj->print(); }
static Obj<T> X;
};
template<typename T>
Obj<T> Obj<T>::X(1.0);
I try to implement the Visitor pattern with templated derived classes
I work with gcc 4.5
here is the VisitorTemplate.hpp, I specialized Derived in the class Visitor, but I'd like to be able to handle any type:
edit : thanks to the suggestions of interjay, the code compiles and runs without errors now
#ifndef VISITORTEMPLATE_HPP_
#define VISITORTEMPLATE_HPP_
#include <iostream>
#include <string>
using namespace std;
template<class T> Derived;
class Visitor
{
public:
virtual void visit(Derived<string> *e) = 0;
};
class Base
{
public:
virtual void accept(class Visitor *v) = 0;
};
template<class T>
Derived: public Base
{
public:
virtual void accept(Visitor *v)
{
v->visit(this);
}
string display(T arg)
{
string s = "This is : " + to_string(arg);
return s;
}
};
class UpVisitor: public Visitor
{
virtual void visit(Derived<string> *e)
{
cout << "do Up on " + e->display("test") << '\n';
}
};
class DownVisitor: public Visitor
{
virtual void visit(Derived<string> *e)
{
cout << "do Down on " + e->display("test") << '\n';
}
};
#endif /* VISITORTEMPLATE_HPP_ */
main.cpp
Base* base = new Derived<string>();
Visitor* up = new UpVisitor();
Visitor* down = new DownVisitor();
base->accept(up);
base->accept(down);
Now my goal is to use Derived in visit without specializing; unfortunately, visit is a virtual method so I can't template it
From Modern C++ - Design Generic Programming and Design Patterns Applied - Andrei Alexandrescu
#include <iostream>
class BaseVisitor
{
public:
virtual ~BaseVisitor() {};
};
template <class T, typename R = int>
class Visitor
{
public:
virtual R visit(T &) = 0;
};
template <typename R = int>
class BaseVisitable
{
public:
typedef R ReturnType;
virtual ~BaseVisitable() {};
virtual ReturnType accept(BaseVisitor & )
{
return ReturnType(0);
}
protected:
template <class T>
static ReturnType acceptVisitor(T &visited, BaseVisitor &visitor)
{
if (Visitor<T> *p = dynamic_cast< Visitor<T> *> (&visitor))
{
return p->visit(visited);
}
return ReturnType(-1);
}
#define VISITABLE() \
virtual ReturnType accept(BaseVisitor &v) \
{ return acceptVisitor(*this, v); }
};
/** example of use */
class Visitable1 : public BaseVisitable<int>
{
/* Visitable accept one BaseVisitor */
public:
VISITABLE();
};
class Visitable2 : public BaseVisitable<int>
{
/* Visitable accept one BaseVisitor */
public:
VISITABLE();
};
class VisitorDerived : public BaseVisitor,
public Visitor<Visitable1, int>,
public Visitor<Visitable2, int>
{
public:
int visit(Visitable1 & c)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
int visit(Visitable2 & c)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
int main(int argc, char **argv)
{
VisitorDerived visitor;
Visitable1 visitable1;
Visitable2 visitable2;
visitable1.accept(visitor);
visitable2.accept(visitor);
}
Is possible to avoid dynamic_cast with CRTP pattern like:
#include <iostream>
class BaseVisitor
{
public:
virtual ~BaseVisitor() {};
};
template <class T>
class Visitor
{
public:
virtual void visit(T &) = 0;
};
template <class Visitable>
class BaseVisitable
{
public:
template <typename T>
void accept(T & visitor)
{
visitor.visit(static_cast<Visitable &>(*this));
}
};
/** example of use */
class Visitable1 : public BaseVisitable<Visitable1>
{
};
class Visitable2 : public BaseVisitable<Visitable2>
{
};
class VisitorDerived : public BaseVisitor,
public Visitor<Visitable1>,
public Visitor<Visitable2>
{
public:
void visit(Visitable1 & c)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
void visit(Visitable2 & c)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
int main(int argc, char **argv)
{
VisitorDerived visitor;
Visitable1 visitable1;
Visitable2 visitable2;
visitable1.accept<VisitorDerived>(visitor);
visitable2.accept<VisitorDerived>(visitor);
}
Your Derived class cannot use Visitor because it hasn't been defined yet (it was only forward declared, and is therefore an incomplete type).
You can fix the compile error by putting the Visitor definition before Derived. You will also need to forward-declare Derived before defining Visitor:
template <class T> class Derived;
class Visitor {
public:
virtual void visit(Derived<string> *e) = 0;
};
template <class T>
class Derived : public Base {
//.... can call Visitor methods here ...
};