I am trying to create abstract class which is a template for another classes. Is it possible to create "flexible" template?
Several classes will inherit from this one, all of them will have the functions with the same name, but with different arguments. The abstract class is "Interface" of inheritance classes - I will use pointer of this one to manage another.
For example we have two classes: A and B.
find method of A class needs only type1 type, but the same method of B class needs type1 and type2 types.
This is how I am creating classes that inherit from template:
class A : public Repository<int> {
public void find(int) override; };
class B : public Repository<int, float> {
public void find(int a, float b) override; };
Its all about the part after public keyword. I don't want to type <int, float> to all classes.
I there any way to overload(?) the template<typename type1, typename type2> and the function?
The code of the abstract class.
#ifndef REPOSITORY_HPP
#define REPOSITORY_HPP
#include <string>
//template<typename type1>
template<typename type1, typename type2>
class Repository
{
protected:
typeSTRING name;
public:
virtual void find(type1) = 0;
//virtual void find(type1, type2) = 0;
};
#endif
You would need variadic template in base class, i.e
#include <iostream>
template <typename ... Args>
class Interface
{
public:
virtual void find(Args... args) = 0;
};
class Impl1 : public Interface<int>
{
public:
void find(int value) override
{
std::cout << "found" << value << std::endl;
}
};
class Impl2 : public Interface<int, float>
{
public:
void find(int value, float other_value) override
{
std::cout << "found" << value << " " << other_value << std::endl;
}
};
int main()
{
Impl1 impl1 {};
impl1.find(5);
Impl2 impl2 {};
impl2.find(5, 10.2);
}
To complement the below comment from #KKMKK, this is how you can get an specific type from Args... (from: get the Nth type of variadic template templates?):
template <typename ... Args>
class Interface
{
public:
using FirstType = typename std::tuple_element<0, std::tuple<Args...> >::type;
virtual void add(FirstType) = 0;
virtual void find(Args... args) = 0;
};
class Impl2 : public Interface<int, float>
{
public:
void add(int value) override
{
std::cout << "found" << value << std::endl;
}
void find(int value, float other_value) override
{
std::cout << "found" << value << " " << other_value << std::endl;
}
};
int main()
{
Impl2 impl2 {};
impl2.add(5);
impl2.find(5, 10.2);
}
Related
I would like to create template class that implements print() method for each type passed as template parameters.
Something like that:
class Interface
{
public:
virtual ~Interface() = default;
virtual void print(int) = 0;
virtual void print(double) = 0;
};
X x<int, double, Interface>;
class X has public method void print() and it works.
The whole code below:
#include <iostream>
#include <type_traits>
struct Printer
{
void print(int i) {std::cout << i << std::endl; }
void print(double d) {std::cout << d << std::endl; }
};
class Interface
{
public:
virtual ~Interface() = default;
virtual void print(int) = 0;
virtual void print(double) = 0;
};
template <typename... Args>
class X;
template <typename Interface>
class X<Interface> : public Interface
{
static_assert(std::is_abstract<Interface>::value, "Last argument should be an interface");
public:
X(Printer printer) {}
using Interface::print;
};
template <typename Arg, typename... Args>
class X<Arg, Args...> : public X<Args...>
{
using Parent = X<Args...>;
public:
using Parent::print;
X(Printer printer_): Parent(printer), printer{printer_} {}
void print(Arg arg) override { printer.print(arg); }
private:
Printer printer;
};
int main()
{
Printer printer;
X<double, int, Interface> x(printer);
x.print(5);
}
As you see class X uses Printer class but the problem is that I would like to have Printer as a template parameter...
Is it possible? How to do that?
As you see class X uses Printer class but the problem is that I would like to have Printer as a template parameter...
Is it possible? How to do that?
Sorry but... I don't see the problem (with a great simplification suggested by Story Teller: place a single Printer object in the ground case case)
template <typename...>
class X;
template <typename Printer, typename Interface>
class X<Printer, Interface> : public Interface
{
static_assert(std::is_abstract<Interface>::value,
"Last argument should be an interface");
public:
X (Printer p0) : printer{p0}
{ }
using Interface::print; // why?
protected:
Printer printer;
};
template <typename Printer, typename Arg, typename... Args>
class X<Printer, Arg, Args...> : public X<Printer, Args...>
{
using Parent = X<Printer, Args...>;
public:
using Parent::print;
using Parent::printer;
X(Printer printer_): Parent{printer_} {}
void print(Arg arg) override { printer.print(arg); }
};
// ....
X<Printer, double, int, Interface> x(printer);
Off topic: attention: you're using printer uninitialized
X(Printer printer_): Parent(printer), printer{printer_} {}
I suppose you should write Parent(printer_)
Assuming that the polymorphic interface is required.
polymorphism reduces the value of variadic template expansion
preserving the deferral of action to an encapsulated printer
A possible solution:
#include <iostream>
#include <type_traits>
// Abstract interface
class PrintInterface
{
public:
virtual ~PrintInterface() = default;
virtual void print(int) = 0;
virtual void print(double) = 0;
};
// An implmentation of PrintInterface that defers to PrinterType
template<class PrinterType>
class ImplementPrintInterface : public PrintInterface
{
public:
ImplementPrintInterface(PrinterType printer)
: printer_(std::move(printer))
{}
virtual void print(int x) override
{
printer_.print(x);
}
virtual void print(double x) override
{
printer_.print(x);
}
private:
PrinterType printer_;
};
// An implementation of a thing that prints ints and doubles.
// This happens to match PrintInterface but there is no inheritance
struct Printer
{
void print(int i) {std::cout << i << std::endl; }
void print(double d) {std::cout << d << std::endl; }
};
// X *is a* PrinterInterface that *uses a* PrinterType
template <typename PrinterType>
class X : public ImplementPrintInterface<PrinterType>
{
public:
X(PrinterType printer = PrinterType())
: ImplementPrintInterface<PrinterType>(std::move(printer))
{}
};
int main()
{
Printer printer;
X<Printer> x(printer);
x.print(5);
}
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 a base class and a bunch of derived classes. Is there any way or mechanism to know all the derived class names programmatically?
Maybe reflection is a good idea, but it's not available on C++. I suppose there will be some kind of template that can finish this job during compilation.
class Base{
public:
virtual void print(){
// This function should print all the names of derived class.
}
virtual Base* getInstance(string class_name){
// This function should return an instance related to the class name.
}
};
class Derived_1 : public Base{ // Suppose we have 100 Derived_X classes,
// so we don't want to add its name to a list manually.
};
int main(){
Base base;
base.print(); // This should print the name of all the derived class.
base.getInstance("Derived_1"); // This should return an instance of Derived_1
return 0;
}
This solution is based on the fact that it seems you are actually looking for a factory. It uses a small macro to ease classes registration, hope you don't care about it.
factory.h
#ifndef __FACTORY_H__
#define __FACTORY_H__
#include <map>
#include <functional>
#include <string>
#include <iostream>
template<class B>
class Factory {
std::map<std::string, std::function<B*()>> s_creators;
public:
static Factory<B>& getInstance() {
static Factory<B> s_instance;
return s_instance;
}
template<class T>
void registerClass(const std::string& name) {
s_creators.insert({name, []() -> B* { return new T(); }});
}
B* create(const std::string& name) {
const auto it = s_creators.find(name);
if (it == s_creators.end()) return nullptr; // not a derived class
return (it->second)();
}
void printRegisteredClasses() {
for (const auto &creator : s_creators) {
std::cout << creator.first << '\n';
}
}
};
#define FACTORY(Class) Factory<Class>::getInstance()
template<class B, class T>
class Creator {
public:
explicit Creator(const std::string& name) {
FACTORY(B).registerClass<T>(name);
}
};
#define REGISTER(base_class, derived_class) \
Creator<base_class, derived_class> s_##derived_class##Creator(#derived_class);
#endif
example.cpp
#include "factory.h"
#include <memory>
class Base {
public:
virtual void printName() const { std::cout << "Base\n"; }
};
class Derived1 : public Base {
public:
virtual void printName() const override { std::cout << "Derived1\n"; }
};
REGISTER(Base, Derived1);
class Derived2 : public Base {
public:
virtual void printName() const override { std::cout << "Derived2\n"; }
};
REGISTER(Base, Derived2);
int main() {
std::cout << "Registered classes:" << std::endl;
FACTORY(Base).printRegisteredClasses();
std::cout << "---" << std::endl;
std::unique_ptr<Base> derived1(FACTORY(Base).create("Derived1"));
derived1->printName();
return 0;
}
Note: requires C++11.
For the getInstance you can declare it a template (needs C++14). To get all the names of the derived classes in the program you probably have to resort to some preprocessor hack.
#include <type_traits>
class Base
{
public:
virtual ~Base () = default;
template < typename T,
typename = std::enable_if_t<std::is_base_of<Base, T>::value, void>
>
T getInstance() { return T{}; }
};
class Derived : public Base {};
class NotDerived {};
int main(){
Base base;
base.getInstance<Derived>();
// error: no matching member function for call to 'getInstance'
//base.getInstance<NotDerived>();
}
Regarding the name of the derived classes, I propose a solution based on a BaseList class/struct, with a static std::set (or other container) of names, a template Base class/struct, that inherit from BaseList and whose template parameter is the derived class (CRTP style) and (to semplify the construction of the derived classes/struct, a C-style macro (I know... macros are distilled evil... but sometimes...) to create the declaration of the derived classes/structs with a necessary static method, that declare the name of the derived class/struct, and a member (that activate the registration of the name).
The following is a full example (unfortunately is a C++11 one)
#include <set>
#include <string>
#include <iostream>
struct BaseList
{
static std::set<std::string> const & derList (std::string const & dn)
{
static std::set<std::string> dl;
if ( dn.size() )
dl.insert(dn);
return dl;
}
static void print ()
{
std::cout << "derived names: ";
for ( auto const & dn : derList("") )
std::cout << dn << ", ";
std::cout << std::endl;
}
};
template <typename Der>
struct Base : public BaseList
{
static std::size_t setNameInList ()
{ return derList(Der::name()).size(); }
static std::size_t id;
};
template <typename Der>
std::size_t Base<Der>::id = setNameInList();
#define setDerived(nameDer) \
struct nameDer : public Base<nameDer>\
{ \
std::size_t idc { id }; \
static std::string name () \
{ return #nameDer; }
setDerived(Derived_1)
// other elements
};
setDerived(Derived_2)
// other elements
};
setDerived(Derived_3)
// other elements
};
int main()
{
BaseList::print();
}
Regarding the getInstance() problem, the only solution that I can imagine is the same solution proposed by Enry Menke (+1), so I suggest that you get the instance through a template type parameter.
I faced a problem that could be solved with the visitor pattern, and because I love reusable code I thought it might be a good idea to have some classes that already do most of the magic for me and which I could reuse later. So what I wanted was something like a Visitor class and a Visitable class, from which I can derive to prepare my deriving class for the use of the visitor pattern. I came up with this code:
template <typename ret = void>
class Visitor
{
public:
typedef ret ReturnType;
protected:
Visitor() {}
~Visitor() {}
};
template <typename BaseType>
class Visitable
{
public:
template <typename Visitor>
typename Visitor::ReturnType applyVisitor(Visitor& visitor)
{
return visitor(static_cast<BaseType*>(this));
}
template <typename Visitor>
typename Visitor::ReturnType applyVisitor(Visitor& visitor) const
{
return visitor(static_cast<BaseType*>(this));
}
protected:
Visitable() {}
~Visitable() {}
};
template <typename VisitorType, typename VisitableType>
inline typename VisitorType::ReturnType applyVisitor(VisitorType visitor, VisitableType visitable)
{
return visitable->applyVisitor(visitor);
}
class Base : public Visitable <Base>
{
public:
virtual void foo() const
{
std::cout << "BASE" << std::endl;
};
std::string foobar() const
{
return "BASE";
};
};
class Derived : public Base, public Visitable<Derived>
{
public:
using Visitable<Derived>::applyVisitor;
void foo() const
{
std::cout << "DERIVED" << std::endl;
};
std::string bar() const
{
return "DERIVED";
};
};
struct MyVisitor : public Visitor < >
{
template <class T>
void operator()(T const var) const
{
var->foo();
}
};
struct MyOtherVisitor : public Visitor <std::string>
{
std::string operator()(Base * const var) const
{
return var->foobar();
}
std::string operator()(Derived * const var) const
{
return var->bar();
}
};
int main(int _Argc, char* _Argv)
{
Base *pVirtualDerived = new Derived();
Base *pBase = new Base();
Derived *pDerived = new Derived();
std::cout << "Member method:" << std::endl;
applyVisitor(MyVisitor(), pVirtualDerived);
applyVisitor(MyVisitor(), pBase);
applyVisitor(MyVisitor(), pDerived);
std::cout << std::endl << "External method:" << std::endl;
std::cout << applyVisitor(MyOtherVisitor(), pVirtualDerived) << std::endl;
std::cout << applyVisitor(MyOtherVisitor(), pBase) << std::endl;
std::cout << applyVisitor(MyOtherVisitor(), pDerived) << std::endl;
}
As one might already guess from the names I was inspired by boost::static_visitor and boost::variant. However, one can also notice that my implementation is flawed in two aspects:
It does not suffice to just inherit from Visitable, I also need to put a using declaration into my class to resolve ambiguity for the applyVisitor method.
It is not really the visitor pattern. Calling applyVisitor with a Base* that actually points to a Derived object does not call Derived::foo but Base::foo. I cannot declare applyVisitor in Visitable<T> virtual because it is a templated method. But I need the template because Visitor<T> is a template class it self and I would like to keep the generic return type for my visitors.
Long story short, can I somehow solve both problems and end up with two classes from which I simply need to derive to prepare my code for the visitor pattern?
There are lots of things to talk about Visitor Design Patterns and C++ inheritance. In the specific case that you described, I think the solutions are:
About the first problem, since the Base class is already inheriting from Visitable, you don't need to inherit from it again in the derived class:
class Derived : public Base
{
public:
void foo() const
{
std::cout << "DERIVED" << std::endl;
};
};
About the second problem, I think you just forgot the virtual keyword in the Base class:
class Base : public Visitable<Base>
{
public:
virtual void foo() const
{
std::cout << "BASE" << std::endl;
};
};
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 ...
};