Template specialisation inherit from specific subclass - c++

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

Related

Is there a way to wrap a function call in or overload a functions call?

My aim is to have a class that inherits from another class in C++ and overloads all of the parents class methods in an identical fashion.
So when a method is called some code is run, the original method is called and a bit more code is run all in the derived class overload method.
class Base
{
Base() {}
~Base() {}
void base_method()
{
// Does something.
}
}
template<class T>
class ClassWrapper : public T
{
public:
ClassWrapper(T base) : T( base ) {}
~ClassWrapper() {}
void wrap_function()
{
// multithread block {
// call base method within multithread block.
this->base_method();
// }
}
}
int main()
{
Base B;
ClassWrapper<Base> C( B );
C.base_method();
return 0;
}
Ideally nothing would be known about the base class but all of its methods could be overridden.
I'm not sure if this is even possible but if it is any suggestions would be great!
With inheritance, you might do:
class Base
{
Base() {}
virtual ~Base() {}
virtual void base_method()
{
// Does something.
}
};
class BaseWrapper : public Base
{
public:
BaseWrapper(Base base) : Bas( base ) {}
void base_method() override
{
// Some code ...
Base::base_method();
// Some code ...
}
}
int main()
{
Base B;
BaseWrapper C( B );
C.base_method();
}
Static polymorphism achieved through CRTP (Curiously Recurring Template Pattern) might be beneficial for you.
Read more about CRTP here and here.
Imagine you have a Wrapper class like:
template <typename Impl>
class Wrapper {
public:
Wrapper() {}
~Wrapper() {}
void some_preparation() {
std::cout << "Wrapper work!" << std::endl;
}
};
and then you have your actual class like:
class MyFoo : public Wrapper<MyFoo> {
public:
MyFoo() {}
~MyFoo() {}
void foo() {
Wrapper::some_preparation();
std::cout << "Derived work!" << std::endl;
}
};
and, eventually, you can use above code like:
MyFoo wrappedFoo;
wrappedFoo.foo();
The result would be:
Wrapper work!
Derived work!
Jarod's answer is a very good one for your question. However, I would like to add an answer more focused on your chosen design rather than the implementation.
Although you said that you want to "overloads all of the parents class methods in an identical fashion", your goal ("the original method is called and a bit more code is run all in the derived class overload method") indicates that it is slightly different.
The first one may indicate inheritance, but the second one may point to factory abstract design pattern (composition over inheritance):
#include<iostream>
class AbstractBar
{
public:
virtual void bar_method() = 0;
};
class Bar1 : public AbstractBar
{
public:
void bar_method() {
std::cout << "Bar 1" << std::endl;
}
};
class Bar2 : public AbstractBar
{
public:
void bar_method() {
std::cout << "Bar 2" << std::endl;
}
};
class Foo
{
public:
Foo(AbstractBar* bar_) : bar(bar_) { }
void foo_method() {
bar->bar_method();
std::cout << "Foo" << std::endl;
}
private:
AbstractBar* bar;
};
int main() {
Bar1 bar;
Foo foo(&bar);
foo.foo_method();
}
Being the output of the code:
Bar 1
Foo
Or a simplified version (based on your needs):
#include<iostream>
class Bar {
public:
void bar_method() {
std::cout << "Bar" << std::endl;
}
};
class Foo {
public:
Foo(Bar* bar_) : bar(bar_) { }
void foo_method() {
bar->bar_method();
std::cout << "Foo" << std::endl;
}
private:
Bar* bar;
};
int main() {
Bar bar;
Foo foo(&bar);
foo.foo_method();
}

How to hide param type of template base class

Not sure if this is even possible but here goes...
I'm trying to hide the param of a template base class by doing the following:
Expose a common interface
Implement template base class that implements the common interface
Implement several concrete derived classes
Use a factory class to instantiate the concrete derived classes
So far so good, but the problem is the return type of my factory class is IBase so the default implementation of foo is called instead of DerivedA or DerivedB :(
Anyway for this approach to work? or back to the drawing board?
// Common interface
class IBase {
public:
virtual std::string foo() { return "IBase"; };
}
// Template base class
template <typename T>
class Base : public IBase {
public:
Base(T value) : m_precious(value) {}
virtual ~Base() {}
protected:
T m_precious;
}
// Concrete derived classes
class DerivedA : public Base<int> {
public:
DerivedA(int value) : Base<int>(value) {}
virtual std::string foo() override {
return "DerivedA";
};
}
class DerivedB : public Base<float> {
public:
DerivedB(float value) : Base<float>(value) {}
virtual std::string foo() override {
return "DerivedB";
};
}
// Factory interface
class Factory {
public:
template<typename T>
static IBase create(T value);
};
template<>
IBase Factory::create<int>(int value) {
return DerivedA(value);
}
template<>
IBase Factory::create<float>(float value) {
return DerivedB(value);
}
// Caller
int main() {
int valueA = 3;
float valueB = 3.14;
// This is how I want to use the API
IBase A = Factory::create(valueA);
IBase B = Factory::create(valueB);
std::cout << A.foo() << std::endl;
std::cout << B.foo() << std::endl;
}
The above code prints:
IBase
IBase
But I want this:
DerivedA
DerivedB
You currently have object slicing, your code should be something like:
// Factory interface
class Factory {
public:
template<typename T>
static std::unique_ptr<IBase> create(T value);
};
template<>
std::unique_ptr<IBase> Factory::create<int>(int value) {
return std::make_unique<DerivedA>(value);
}
template<>
std::unique_ptr<IBase> Factory::create<float>(float value) {
return std::make_unique<DerivedB>(value);
}
With usage:
auto A = Factory::create(valueA);
auto B = Factory::create(valueB);
std::cout << A->foo() << std::endl;
std::cout << B->foo() << std::endl;

Can I get the current class type id from a static base method?

Is there anyway to get a type from a static base class method? For instance
class A
{
static std::type_info getClassType
{
// What do I do here
}
};
class B : public A
{
};
B instance;
auto my_type = instance::getClassType()
With C++'s lack of static variable overloading, I am having a hard time figuring out a way to determine class type across classes without doing a special virtual function in every child class which I am trying to avoid due to the sheer number.
Make a class that will be a template.
Subclass from it. Pass the child type as the template parameter.
With that, base class will know the child. The T will be the child type.
Code:
#include <iostream>
using namespace std;
template<typename T> class thebase
{
static T instance;
public:
static T& getInstance() { return instance; }
};
template <typename T> T thebase<T>::instance;
class sub1 : public thebase<sub1> {
public: void tell() { std::cout << "hello1: " << this << std::endl; }
};
class sub2 : public thebase<sub2> {
public: void tell() { std::cout << "hello2: " << this << std::endl; }
};
int main() {
sub1& ref1 = sub1::getInstance();
sub1& ref2 = sub1::getInstance();
std::cout << ((&ref1) == (&ref2)) << std::endl;
sub1::getInstance().tell();
sub2::getInstance().tell();
sub1::getInstance().tell();
sub2::getInstance().tell();
return 0;
}
Output:
1
hello1: 0x55874bff1193
hello2: 0x55874bff1192
hello1: 0x55874bff1193
hello2: 0x55874bff1192
This kind of code pattern is sometimes called CRTP
it boils down to there being a manager class that keeps track of one instance of a variety of classes and their states. You may use this singleton "instance" of these sub classes, but I want to be able to say MySubClass::instance() and then have it get the correct instance from the manager without having to write it in each sub class.
You can implement the managed classes using CRTP ("Curiously recurring template pattern") so a base class knows the derived class types and can then delegate that information to the manager class.
Try something like this:
#include <map>
#include <typeinfo>
#include <typeindex>
class Base {
public:
virtual ~Base() {}
};
class Manager
{
private:
static std::map<std::type_index, Base*> m_instances;
public:
template<typename T>
static void addInstance(Base *inst) {
if (!m_instances.insert(std::make_pair(std::type_index(typeid(T)), inst)).second)
throw ...; // only 1 instance allowed at a time!
}
template<typename T>
static void removeInstance() {
auto iter = m_instances.find(std::type_index(typeid(T)));
if (iter != m_instances.end())
m_instances.erase(iter);
}
template<typename T>
static T* getInstance() {
auto iter = m_instances.find(std::type_index(typeid(T)));
if (iter != m_instances.end())
return static_cast<T*>(iter->second);
return nullptr;
}
};
std::map<std::type_index, Base*> Manager::m_instances;
template<class Derived>
class A : public Base
{
public:
A() {
Manager::addInstance<Derived>(this);
}
~A() {
Manager::removeInstance<Derived>();
}
static Derived* getInstance() {
return Manager::getInstance<Derived>();
}
};
class B : public A<B>
{
...
};
class C : public A<C>
{
...
};
B b_inst;
C c_inst;
...
B *pB = B::getInstance();
if (pB) ...
C *pC = C::getInstance();
if (pC) ...
Live Demo
Based on your own example of code in your own answer, here's a final result working:
# include <iostream>
# include <typeinfo>
template <class T>
class A
{
public:
static const std::type_info& getClassType()
{
return typeid(T);
}
};
class B : public A<B>
{ /* ... */ };
class C : public A<C>
{ /* ... */};
class D : public A<D>
{ /* ... */};
int main()
{
B b; C c; D d;
auto& b_type = b.getClassType();
auto& c_type = c.getClassType();
auto& d_type = d.getClassType();
std::cout << b_type.name() << std::endl;
std::cout << c_type.name() << std::endl;
std::cout << d_type.name() << std::endl;
}
Output:
1B 1C 1D
Someone above mentioned the CRTP or "Curiously recurring template pattern". Using this, I have not tested it, but it appears I may be able to write:
template <class T>
class A
{
static std::type_info getClassType
{
return typeid(T);
}
};
class B : public A<B>
{
};
B instance;
auto my_type = instance::getClassType()

C++: Inheriting from template class with possible varying constructor arguments

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;
};

Using the Visitor Pattern with template derived classes

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 ...
};