I have been looking for a way to use both templating and polymorphism at the same time. Here's a simplified version of my problem:
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
//*******************************************************************
//*******************************************************************
struct DerivedStuff1
{
static void eval() { cout << "evaluating DerivedStuff1" << endl; }
};
struct DerivedStuff2
{
static void eval() { cout << "evaluating DerivedStuff2" << endl; }
};
//*******************************************************************
//*******************************************************************
class BaseClass
{
public:
template<typename StuffType> virtual void eval() const = 0;
};
class DerivedClass1 : public BaseClass
{
public:
template<typename StuffType> virtual void eval() const
{
std::cout << "We are in DerivedClass1: ";
StuffType::eval();
}
};
class DerivedClass2 : public BaseClass
{
public:
template<typename StuffType> virtual void eval() const
{
std::cout << "We are in DerivedClass2: ";
StuffType::eval();
}
};
int main()
{
BaseClass* c1 = new DerivedClass1;
c1->eval<DerivedStuff1>();
c1->eval<DerivedStuff2>();
BaseClass* c2 = new DerivedClass2;
c2->eval<DerivedStuff1>();
c2->eval<DerivedStuff2>();
return 0;
}
This code does not compile because virtual template functions are not allowed in C++. I found a few approaches to tackle this problem (CRTP, etc.) but none of them were really satisfying. Is there no elegant way to get around that issue?
The visitor pattern turns run-time polymorphism on its side and makes runtime-polymorphic function templates possible. It has other legitimate uses apart from templatisation, so I guess you can call it somewhat elegant.
Your example can look as follows:
#include <iostream>
class DerivedStuff1 {
public:
static void eval() { std::cout << "Evaluating DerivedStuff1\n"; }
};
class DerivedStuff2 {
public:
static void eval() { std::cout << "Evaluating DerivedStuff2\n"; }
};
class DerivedClass1; class DerivedClass2;
class BaseClassVisitor {
public:
virtual void visit(DerivedClass1&) = 0;
virtual void visit(DerivedClass2&) = 0;
};
class BaseClass {
public:
virtual void accept(BaseClassVisitor& v) = 0;
};
class DerivedClass1 : public BaseClass
{
public:
virtual void accept(BaseClassVisitor& v) { v.visit(*this); }
};
class DerivedClass2 : public BaseClass
{
public:
virtual void accept(BaseClassVisitor& v) { v.visit(*this); }
};
template <typename StuffType>
class EvalVisitor : public BaseClassVisitor
{
virtual void visit(DerivedClass1&) {
std::cout << "We are in DerivedClass1: ";
StuffType::eval();
}
virtual void visit(DerivedClass2&) {
std::cout << "We are in DerivedClass2: ";
StuffType::eval();
}
};
int main()
{
EvalVisitor<DerivedStuff1> e1;
EvalVisitor<DerivedStuff2> e2;
BaseClass* c1 = new DerivedClass1;
c1->accept(e1);
c1->accept(e2);
BaseClass* c2 = new DerivedClass2;
c2->accept(e1);
c2->accept(e2);
return 0;
}
Demo
Of course all shortcomings of Visitor apply here.
You could reinvent the vtable and resolve the function pointer at run time. You will, however, have to explicitely instantiate the template on the derived class, but I don't see any approach to this that won't require that.
Quick and dirty example:
#include <map>
#include <iostream>
class Base {
public:
typedef void (Base::*eval_ptr)();
using eval_vtable = std::map<std::type_index, eval_ptr>;
Base(eval_vtable const& eval_p) : eval_ptrs(eval_p) {}
template<typename T>
void eval() {
auto handler = eval_ptrs.find(type_index(typeid(T)));
if(handler != eval_ptrs.end()) {
auto handler_ptr = handler->second;
(this->*handler_ptr)();
}
}
eval_vtable const& eval_ptrs;
};
class Derived : public Base {
public:
Derived()
: Base(eval_functions) {}
template<typename T>
void eval_impl() {
std::cout << typeid(T).name() << "\n";
}
static eval_vtable eval_functions;
};
Base::eval_vtable Derived::eval_functions = {
{ type_index(typeid(int)), eval_ptr(&Derived::eval_impl<int>) },
{ type_index(typeid(float)), eval_ptr(&Derived::eval_impl<float>) },
{ type_index(typeid(short)), eval_ptr(&Derived::eval_impl<short>) },
};
int main(int argc, const char* argv[]) {
Derived x;
Base * x_as_base = &x;
x_as_base->eval<int>(); // calls Derived::eval_impl<int>()
return 0;
}
This won't be exactly fast, but it will give you the closest thing to templated virtual functions that I can think of.
Edit: For the record I don't advocate anyone use this. I would much rather revisit the design to avoid being painted in this particular corner in the first place. Please consider my answer as an academic solution to a theoretical problem, not an actual engineering recommendation.
Since virtual template methods in C++ arent allowed, you can make a class template and call static function of class template param.
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
//*******************************************************************
//*******************************************************************
struct DerivedStuff1
{
static void eval() { cout << "evaluating DerivedStuff1" << endl; }
};
struct DerivedStuff2
{
static void eval() { cout << "evaluating DerivedStuff2" << endl; }
};
//*******************************************************************
//*******************************************************************
class BaseClass
{
public:
virtual void eval() const = 0;
};
template<typename StuffType>
class DerivedClass1 : public BaseClass
{
public:
virtual void eval() const
{
std::cout << "We are in DerivedClass1: ";
StuffType::eval();
}
};
template<typename StuffType>
class DerivedClass2 : public BaseClass
{
public:
virtual void eval() const
{
std::cout << "We are in DerivedClass2: ";
StuffType::eval();
}
};
int main()
{
BaseClass* c1 = new DerivedClass1<DerivedStuff1>;
c1->eval();
c1 = new DerivedClass1<DerivedStuff2>;
c1->eval();
BaseClass* c2 = new DerivedClass2<DerivedStuff1>;
c2->eval();
c2 = new DerivedClass2<DerivedStuff2>;
c2->eval();
// deletes
return 0;
}
Output
We are in DerivedClass1: evaluating DerivedStuff1
We are in DerivedClass1: evaluating DerivedStuff2
We are in DerivedClass2: evaluating DerivedStuff1
We are in DerivedClass2: evaluating DerivedStuff2
You cannot mix templates (compile time) and polymorphic (runtime). That's it.
So, a posible workaround is remove templates. For example, it could take a function pointer or just more polymorphism:
//*******************************************************************
//*******************************************************************
struct InterfaceStuff{
virtual void eval() = 0;
}
struct DerivedStuff1 : public InterfaceStuff
{
void eval() { cout << "evaluating DerivedStuff1" << endl; }
};
struct DerivedStuff2 : public InterfaceStuff
{
void eval() { cout << "evaluating DerivedStuff2" << endl; }
};
//*******************************************************************
//*******************************************************************
class BaseClass
{
public:
virtual void eval(InterfaceStuff* interface) const = 0;
};
class DerivedClass1 : public BaseClass
{
public:
virtual void eval(InterfaceStuff* interface) const
{
std::cout << "We are in DerivedClass1: ";
interface->eval();
}
};
class DerivedClass2 : public BaseClass
{
public:
virtual void eval(InterfaceStuff* interface) const
{
std::cout << "We are in DerivedClass2: ";
interface->eval();
}
};
Another posible workaround is remove polymorphism, just use more templates:
struct DerivedStuff1
{
static void eval() { cout << "evaluating DerivedStuff1" << endl; }
};
struct DerivedStuff2
{
static void eval() { cout << "evaluating DerivedStuff2" << endl; }
};
//*******************************************************************
//*******************************************************************
class BaseClass
{
public:
template<typename Eval,typename StuffType> void eval() const
{
Eval::eval();
StuffType::eval();
}
};
class DerivedClass1 : public BaseClass
{
};
class DerivedClass2 : public BaseClass
{
};
One way of another, you have to choose one.
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;
};
Is it possible to do such things in C++14. I have a base class as follows:
#include <iostream>
class AbstractElement;
class ConcreteElement;
class SuperConcreteElement;
class B
{
public:
void bar(AbstractElement*)
{
std::cout << "Abstract element" << std::endl;
}
void bar(ConcreteElement*)
{
std::cout << "Concrete element" << std::endl;
}
void bar(SuperConcreteElement*)
{
std::cout << "Super concrete element" << std::endl;
}
};
class AbstractElement
{
public:
virtual void foo() = 0;
};
class ConcreteElement : public AbstractElement
{
private:
B _b;
public:
void foo()
{
_b.bar(this); //1
}
};
class SuperConcreteElement : public AbstractElement
{
private:
B _b;
public:
void foo()
{
_b.bar(this); //2
}
};
int main()
{
AbstractElement *e = new ConcreteElement();
e -> foo(); //Prints Concrete element
}
As you can see at //1 and //2, the function's body is completely similar. But I can't quite move it into a base class because of depending on the static type of this. In spite of that fact, I wouldn't like to write absolutely the same code every time I need to add one more subclass of AbstractElement. So, I need some kind of mechanism which provides us with the facility to inject code into a function.
As long as marcos are not very desirable solution, I'd like to ask about some tricks that can be done in C++14 for solving such a problem.
Yes, it is possible using CRTP:
#include <iostream>
class AbstractElement;
class ConcreteElement;
class SuperConcreteElement;
class B
{
public:
void bar(AbstractElement*)
{
std::cout << "Abstract element" << std::endl;
}
void bar(ConcreteElement*)
{
std::cout << "Concrete element" << std::endl;
}
void bar(SuperConcreteElement*)
{
std::cout << "Super concrete element" << std::endl;
}
};
class AbstractElement
{
public:
virtual void foo() = 0;
};
template <class T>
class CRTPAbstractElement : public AbstractElement
{
B _b;
public:
virtual void foo()
{
T* t = dynamic_cast<T *>(this);
_b.bar(t);
}
};
class ConcreteElement : public CRTPAbstractElement<ConcreteElement>
{
};
class SuperConcreteElement : public CRTPAbstractElement<SuperConcreteElement>
{
};
int main()
{
AbstractElement *e = new ConcreteElement();
e -> foo(); //Prints Concrete element
}
By adding an intermediate CRTP class we are able to cast a pointer to the base class to a pointer to the derived class. Thus solving the issue of code duplication.
An example of Strategy Pattern from the book, Head First Design Patterns, was written in C++ at [here]. I'm practicing to transform it into C++11 style according to Effective GoF Patterns with C++11 and Boost as showing below.
The Quack behavior:
struct Quack {
static void quack()
{
std::cout << __FUNCTION__ << std::endl;
}
};
struct MuteQuack {
static void quack()
{
std::cout << __FUNCTION__ << std::endl;
}
};
The Fly behavior:
struct FlyWithWings {
public:
static void fly()
{
std::cout << __FUNCTION__ << std::endl;
}
};
struct FlyNoWay {
public:
static void fly()
{
std::cout << __FUNCTION__ << std::endl;
}
};
The Duck hierarchy:
class Duck
{
public:
typedef std::function<void(void)> QUACK;
typedef std::function<void(void)> FLY;
public:
Duck(const QUACK &q, const FLY &f)
: m_Quack(q), m_Fly(f) {}
virtual ~Duck()
{
}
void perform_quack()
{
m_Quack();
}
void perform_fly()
{
m_Fly();
}
protected:
QUACK m_Quack;
FLY m_Fly;
private:
Duck(const Duck&) = delete;
Duck& operator=(const Duck&) = delete;
};
class MallardDuck
: public Duck
{
public:
MallardDuck()
: Duck(&Quack::quack, &FlyWithWings::fly)
{
}
};
class PaintedDuck
: public Duck
{
public:
PaintedDuck()
: Duck(&MuteQuack::quack, &FlyNoWay::fly)
{
}
};
So far so good, the client works well.
int main()
{
MallardDuck x1;
x1.perform_quack();
x1.perform_fly();
PaintedDuck x2;
x2.perform_quack();
x2.perform_fly();
return 0;
}
Now I would like to extend to a new class RubberDuck to Duck hierarchy, and the RubberDuck uses a new fly behavior FlyWithRocket which has a object state. As following:
A new Fly behavior:
class FlyWithRocket {
public:
FlyWithRocket() : m_Energy(3) {}
void fly()
{
if(m_Energy > 0)
{
fly_with_rocket();
--m_Energy;
}
else
{
fly_out_of_energy();
}
}
private:
void fly_with_rocket()
{
std::cout << __FUNCTION__ << std::endl;
}
void fly_out_of_energy()
{
std::cout << __FUNCTION__ << std::endl;
}
unsigned int m_Energy;
};
A new Duck type:
class RubberDuck
: public Duck
{
public:
RubberDuck()
: Duck(&MuteQuack::quack, std::bind(&FlyWithRocket::fly, std::ref(m_flyrocket)))
, m_flyrocket()
{
}
private:
FlyWithRocket m_flyrocket;
};
From now I'm wondering that the rule of the order of member initialization. The base Duck initializes before the member m_flyrocket, but note that the base Duck is initialized with binding m_flyrocket which is not initialized yet.
As result as I run it in VS2013, this works without something wrong at run-time.
But is the code actually not safe? If not, how could I modify to a better design?
It's not safe, but it's unlikely to break unless you call m_Fly() from the base class constructor.
You can easily avoid this though, by either:
giving the base class constructor a dummy or default-constructed std::function, and re-assigning m_Fly to your bind functor in the derived class constructor
RubberDuck()
: Duck(&MuteQuack::quack, std::function<void()>())
{
m_Fly = std::bind(&FlyWithRocket::fly, std::ref(m_flyrocket));
}
making FlyWithRocket a functor itself (just rename void fly to void operator()) and passing it by value instead of keeping a private member (it will be owned by the m_Fly function object, and you can access it via std::function::target<FlyWithRocket>() if you need)
class FlyWithRocket {
public:
FlyWithRocket() : m_Energy(3) {}
void operator() () {
// ...
RubberDuck()
: Duck(&MuteQuack::quack, FlyWithRocket()) {}
first off: I have read and I know now that a virtual template member function is not (yet?) possible in C++. A workaround would be to make the class a template and then use the template-argument also in the member-function.
But in the context of OOP, I find that the below example would not be very "natural" if the class was actually a template. Please note that the code is actually not working, but the gcc-4.3.4 reports: error: templates may not be ‘virtual’
#include <iostream>
#include <vector>
class Animal {
public:
template< class AMOUNT >
virtual void eat( AMOUNT amount ) const {
std::cout << "I eat like a generic Animal." << std::endl;
}
virtual ~Animal() {
}
};
class Wolf : public Animal {
public:
template< class AMOUNT >
void eat( AMOUNT amount) const {
std::cout << "I eat like a wolf!" << std::endl;
}
virtual ~Wolf() {
}
};
class Fish : public Animal {
public:
template< class AMOUNT >
void eat( AMOUNT amount) const {
std::cout << "I eat like a fish!" << std::endl;
}
virtual ~Fish() {
}
};
class GoldFish : public Fish {
public:
template< class AMOUNT >
void eat( AMOUNT amount) const {
std::cout << "I eat like a goldfish!" << std::endl;
}
virtual ~GoldFish() {
}
};
class OtherAnimal : public Animal {
virtual ~OtherAnimal() {
}
};
int main() {
std::vector<Animal*> animals;
animals.push_back(new Animal());
animals.push_back(new Wolf());
animals.push_back(new Fish());
animals.push_back(new GoldFish());
animals.push_back(new OtherAnimal());
for (std::vector<Animal*>::const_iterator it = animals.begin(); it != animals.end(); ++it) {
(*it)->eat();
delete *it;
}
return 0;
}
So creating a "Fish< Amount > foo" is kind of strange. However, it seems desirable to me to provide an arbitrary amount of food to eat for each animal.
Thus, I am searching a solution about how to achieve something like
Fish bar;
bar.eat( SomeAmount food );
This becomes particularly useful when looking at the for-loop. One might like to feed a specific amount (FoodAmount) to all of the different animals (via eat() and bind1st() e.g.), it could not be done that easily, although I wound find this very inuitive (and thus to some extent "natural). While some might want to argue now that this is due to the "uniform"-character of a vector, I think/wish that it should be possible to achieve this and I really would like to know how, as this is puzzling me for quite some time now...
[EDIT]
To perhaps clarify the motivation behind my question, I want to program an Exporter-class and let different, more specialized classes derive from it. While the top-level Exporter-class is generally only for cosmetic/structural purpose, a GraphExporter-class is derived, that should again serve as a base-class for even more specialzed export. However, similar to the Animal-example, I would like to be able to define GraphExporter* even on specialized/derived classes (e.g. on SpecialGraphExplorer) but when calling "write( out_file )", it should call the appropriate member function for SpecialGraphExporter instead of GraphExporter::write( out_file).
Maybe this makes my situation and intentions clearer.
Best,
Shadow
After some thinking I recognized this as the classic multi-method requirement, i.e. a method that dispatches based on the runtime type of more than one parameter. Usual virtual functions are single dispatch in comparison (and they dispatch on the type of this only).
Refer to the following:
Andrei Alexandrescu has written (the seminal bits for C++?) on implementing multi-methods using generics in 'Modern C++ design'
Chapter 11: "Multimethods" - it implements basic multi-methods, making them logarithmic (using ordered typelists) and then going all the way to constant-time multi-methods. Quite powerful stuff !
A codeproject article that seems to have just such an implementation:
no use of type casts of any kind (dynamic, static, reinterpret, const or C-style)
no use of RTTI;
no use of preprocessor;
strong type safety;
separate compilation;
constant time of multimethod execution;
no dynamic memory allocation (via new or malloc) during multimethod call;
no use of nonstandard libraries;
only standard C++ features is used.
C++ Open Method Compiler, Peter Pirkelbauer, Yuriy Solodkyy, and Bjarne Stroustrup
The Loki Library has A MultipleDispatcher
Wikipedia has quite a nice simple write-up with examples on Multiple Dispatch in C++.
Here is the 'simple' approach from the wikipedia article for reference (the less simple approach scales better for larger number of derived types):
// Example using run time type comparison via dynamic_cast
struct Thing {
virtual void collideWith(Thing& other) = 0;
}
struct Asteroid : Thing {
void collideWith(Thing& other) {
// dynamic_cast to a pointer type returns NULL if the cast fails
// (dynamic_cast to a reference type would throw an exception on failure)
if (Asteroid* asteroid = dynamic_cast<Asteroid*>(&other)) {
// handle Asteroid-Asteroid collision
} else if (Spaceship* spaceship = dynamic_cast<Spaceship*>(&other)) {
// handle Asteroid-Spaceship collision
} else {
// default collision handling here
}
}
}
struct Spaceship : Thing {
void collideWith(Thing& other) {
if (Asteroid* asteroid = dynamic_cast<Asteroid*>(&other)) {
// handle Spaceship-Asteroid collision
} else if (Spaceship* spaceship = dynamic_cast<Spaceship*>(&other)) {
// handle Spaceship-Spaceship collision
} else {
// default collision handling here
}
}
}
Obviously, virtual member function templates are not allowed and could not be realized even theoretically. To build a base class' virtual table, there needs to be a finite number of virtual function-pointer entries. A function template would admit an indefinite amount of "overloads" (i.e. instantiations).
Theoretically-speaking, a language (like C++) could allow virtual member function templates if it had some mechanism to specify the actual (finite) list of instantiations. C++ does have that mechanism (i.e. explicit template instantiations), so I guess it could be possible to do this in a newer C++ standard (although I have no idea what trouble it would entail for compiler vendors to implement this feature). But, that's just a theoretical discussion, in practice, this is simply not allowed. The fact remains, you have to make the number of virtual functions finite (no templates allowed).
Of course, that doesn't mean that class template cannot have virtual functions, nor does it mean that virtual functions cannot call function templates. So, there are many solutions in that vein (like the Visitor pattern or other schemes).
One solution that, I think, serves your purpose (although it is hard to comprehend) elegantly is the following (which is basically a visitor pattern):
#include <iostream>
#include <vector>
struct Eater {
virtual void operator()(int amount) const = 0;
virtual void operator()(double amount) const = 0;
};
template <typename EaterType>
struct Eater_impl : Eater {
EaterType& data;
Eater_impl(EaterType& aData) : data(aData) { };
virtual void operator()(int amount) const { data.eat_impl(amount); };
virtual void operator()(double amount) const { data.eat_impl(amount); };
};
class Animal {
protected:
Animal(Eater& aEat) : eat(aEat) { };
public:
Eater& eat;
virtual ~Animal() { delete &eat; };
};
class Wolf : public Animal {
private:
template< class AMOUNT >
void eat_impl( AMOUNT amount) const {
std::cout << "I eat like a wolf!" << std::endl;
}
public:
friend struct Eater_impl<Wolf>;
Wolf() : Animal(*(new Eater_impl<Wolf>(*this))) { };
virtual ~Wolf() { };
};
class Fish : public Animal {
private:
template< class AMOUNT >
void eat_impl( AMOUNT amount) const {
std::cout << "I eat like a fish!" << std::endl;
}
public:
friend struct Eater_impl<Fish>;
Fish() : Animal(*(new Eater_impl<Fish>(*this))) { };
virtual ~Fish() { };
};
int main() {
std::vector<Animal*> animals;
animals.push_back(new Wolf());
animals.push_back(new Fish());
for (std::vector<Animal*>::const_iterator it = animals.begin(); it != animals.end(); ++it) {
(*it)->eat(int(0));
(*it)->eat(double(0.0));
delete *it;
};
return 0;
};
The above is a neat solution because it allows you to define a finite number of overloads that you want in one place only (in the Eater_impl class template) and all you need in the derived class is a function template (and possibly additional overloads, for special cases). There is, of course, a bit of overhead, but I guess that a bit more thought could be put into it to reduce the overhead (additional reference storage and dynamic allocation of Eater_impl). I guess, the curiously recurring template pattern could probably be employed somehow to this end.
I think the visitor pattern can be a solution.
UPDATE
I finished my example:
#include <iostream>
#include <vector>
#include <boost/shared_ptr.hpp>
class Animal;
class Wolf;
class Fish;
class Visitor
{
public:
virtual void visit(const Animal& p_animal) const = 0;
virtual void visit(const Wolf& p_animal) const = 0;
virtual void visit(const Fish& p_animal) const = 0;
};
template<class AMOUNT>
class AmountVisitor : public Visitor
{
public:
AmountVisitor(AMOUNT p_amount) : m_amount(p_amount) {}
virtual void visit(const Animal& p_animal) const
{
std::cout << "I eat like a generic Animal." << std::endl;
}
virtual void visit(const Wolf& p_animal) const
{
std::cout << "I eat like a wolf!" << std::endl;
}
virtual void visit(const Fish& p_animal) const
{
std::cout << "I eat like a fish!" << std::endl;
}
AMOUNT m_amount;
};
class Animal {
public:
virtual void Accept(const Visitor& p_visitor) const
{
p_visitor.visit(*this);
}
virtual ~Animal() {
}
};
class Wolf : public Animal {
public:
virtual void Accept(const Visitor& p_visitor) const
{
p_visitor.visit(*this);
}
};
class Fish : public Animal {
public:
virtual void Accept(const Visitor& p_visitor) const
{
p_visitor.visit(*this);
}
};
int main()
{
typedef boost::shared_ptr<Animal> TAnimal;
std::vector<TAnimal> animals;
animals.push_back(TAnimal(new Animal()));
animals.push_back(TAnimal(new Wolf()));
animals.push_back(TAnimal(new Fish()));
AmountVisitor<int> amount(10);
for (std::vector<TAnimal>::const_iterator it = animals.begin(); it != animals.end(); ++it) {
(*it)->Accept(amount);
}
return 0;
}
this prints:
I eat like a generic Animal.
I eat like a wolf!
I eat like a fish!
Per Mikael's post, I have made another offshoot, using the CRTP and following Eigen's style of using derived() for an explicit subclass reference:
// Adaptation of Visitor Pattern / CRTP from:
// http://stackoverflow.com/a/5872633/170413
#include <iostream>
using std::cout;
using std::endl;
class Base {
public:
virtual void tpl(int x) = 0;
virtual void tpl(double x) = 0;
};
// Generics for display
template<typename T>
struct trait {
static inline const char* name() { return "T"; }
};
template<>
struct trait<int> {
static inline const char* name() { return "int"; }
};
template<>
struct trait<double> {
static inline const char* name() { return "double"; }
};
// Use CRTP for dispatch
// Also specify base type to allow for multiple generations
template<typename BaseType, typename DerivedType>
class BaseImpl : public BaseType {
public:
void tpl(int x) override {
derived()->tpl_impl(x);
}
void tpl(double x) override {
derived()->tpl_impl(x);
}
private:
// Eigen-style
inline DerivedType* derived() {
return static_cast<DerivedType*>(this);
}
inline const DerivedType* derived() const {
return static_cast<const DerivedType*>(this);
}
};
// Have Child extend indirectly from Base
class Child : public BaseImpl<Base, Child> {
protected:
friend class BaseImpl<Base, Child>;
template<typename T>
void tpl_impl(T x) {
cout << "Child::tpl_impl<" << trait<T>::name() << ">(" << x << ")" << endl;
}
};
// Have SubChild extend indirectly from Child
class SubChild : public BaseImpl<Child, SubChild> {
protected:
friend class BaseImpl<Child, SubChild>;
template<typename T>
void tpl_impl(T x) {
cout << "SubChild::tpl_impl<" << trait<T>::name() << ">(" << x << ")" << endl;
}
};
template<typename BaseType>
void example(BaseType *p) {
p->tpl(2);
p->tpl(3.0);
}
int main() {
Child c;
SubChild sc;
// Polymorphism works for Base as base type
example<Base>(&c);
example<Base>(&sc);
// Polymorphism works for Child as base type
example<Child>(&sc);
return 0;
}
Output:
Child::tpl_impl<int>(2)
Child::tpl_impl<double>(3)
SubChild::tpl_impl<int>(2)
SubChild::tpl_impl<double>(3)
SubChild::tpl_impl<int>(2)
SubChild::tpl_impl<double>(3)
This snippet may be found in source here: repro:c808ef0:cpp_quick/virtual_template.cc
Virtual template function is not allowed. However you can use one OR the other here.
You could make an interface using virtual methods and implement your various animals in terms of having an eating interface. (i.e. PIMPL)
Less human intuitive would be having a non-member non-friend template function as a free function which could take templated const reference to any animal and make them eat accordingly.
For the record you don't need templates here. Pure virtual abstract method on the base class is enough to force and interface where all animals must eat and define how they do so with an override, providing a regular virtual would be enough to say all animals can eat but if they don't have a specific way then they can use this default way.
You can create a template class with virtual function, and implement the function in the derived class without using template in the follwing way:
a.h:
template <class T>
class A
{
public:
A() { qDebug() << "a"; }
virtual A* Func(T _template) { return new A;}
};
b.h:
class B : public A<int>
{
public:
B();
virtual A* Func(int _template) { return new B;}
};
and the function CTOR and call
A<int>* a1=new B;
int x=1;
a1->Func(x);
unfortunately i havn't found a way to create a virtual function with template parameters without declaring the class as a template and it template type on the dervied class
I have copied your code and modified it, so now it should work exactly as you want:
#include <iostream>
#include <vector>
//defined new enum type
enum AnimalEnum
{
animal,
wolf,
fish,
goldfish,
other
};
//forward declarations
class Wolf;
class Fish;
class GoldFish;
class OtherAnimal;
class Animal {
private:
AnimalEnum who_really_am_I;
void* animal_ptr;
public:
//declared new constructors overloads for each type of animal
Animal(const Animal&);
Animal(const Wolf&);
Animal(const Fish&);
Animal(const GoldFish&);
Animal(const OtherAnimal&);
template< class AMOUNT >
/*removed the virtual keyword*/ void eat( AMOUNT amount ) const {
switch (this->who_really_am_I)
{
case AnimalEnum::other: //You defined OtherAnimal so that it doesn't override the eat action, so it will uses it's Animal's eat
case AnimalEnum::animal: std::cout << "I eat like a generic Animal." << std::endl; break;
case AnimalEnum::wolf: ((Wolf*)this->animal_ptr)->eat(amount); break;
case AnimalEnum::fish: ((Fish*)this->animal_ptr)->eat(amount); break;
case AnimalEnum::goldfish: ((GoldFish*)this->animal_ptr)->eat(amount) break;
}
}
void DeleteMemory() { delete this->animal_ptr; }
virtual ~Animal() {
//there you can choose if whether or not to delete "animal_ptr" here if you want or not
}
};
class Wolf : public Animal {
public:
template< class AMOUNT >
void eat( AMOUNT amount) const {
std::cout << "I eat like a wolf!" << std::endl;
}
virtual ~Wolf() {
}
};
class Fish : public Animal {
public:
template< class AMOUNT >
void eat( AMOUNT amount) const {
std::cout << "I eat like a fish!" << std::endl;
}
virtual ~Fish() {
}
};
class GoldFish : public Fish {
public:
template< class AMOUNT >
void eat( AMOUNT amount) const {
std::cout << "I eat like a goldfish!" << std::endl;
}
virtual ~GoldFish() {
}
};
class OtherAnimal : public Animal {
//OtherAnimal constructors must be defined here as Animal's constructors
OtherAnimal(const Animal& a) : Animal(a) {}
OtherAnimal(const Wolf& w) : Animal(w) {}
OtherAnimal(const Fish& f) : Animal(f) {}
OtherAnimal(const GoldFish& g) : Animal(g) {}
OtherAnimal(const OtherAnimal& o) : Animal(o) {}
virtual ~OtherAnimal() {
}
};
//OtherAnimal will be useful only if it has it's own actions and members, because if not, typedef Animal OtherAnimal or using OtherAnimal = Animal can be used, and it can be removed from above declarations and below definitions
//Here are the definitions of Animal constructors that were declared above/before:
Animal::Animal(const Animal& a) : who_really_am_I(AnimalEnum::animal), animal_ptr(nullptr) {}
Animal::Animal(const Wolf& w) : who_really_am_I(AnimalEnum::wolf), animal_ptr(new Wolf(w)) {}
Animal::Animal(const Fish& f) : who_really_am_I(AnimalEnum::fish), animal_ptr(new Fish(f)) {}
Animal::Animal(const GoldFish& g) : who_really_am_I(AnimalEnum::goldfish), animal_ptr(new GoldFish(g)) {}
Animal::Animal(const OtherAnimal& o) :
who_really_am_I(AnimalEnum::other), animal_ptr(new OtherAnimal(o)) {}
int main() {
std::vector<Animal> animals;
animals.push_back(Animal());
animals.push_back(Wolf()); //Wolf is converted to Animal via constructor
animals.push_back(Fish()); //Fish is converted to Animal via constructor
animals.push_back(GoldFish()); //GoldFish is converted to Animal via constructor
animals.push_back(OtherAnimal()); //OtherAnimal is converted to Animal via constructor
for (std::vector<Animal>::const_iterator it = animals.begin(); it != animals.end(); ++it) {
it->eat(); //this is Animal's eat that invokes other animals eat
//delete *it; Now it should be:
it->DeleteMemory();
}
animals.clear(); //All animals have been killed, and we don't want full vector of dead animals.
return 0;
}
In you scenario, you are trying to mix compile time polymorphism with runtime polymorphism, but it cannot be done in this "direction".
Essential, your AMOUNT template argument represents an expected interface for the type to implement based on the union of all the operations each implementation of eat uses. If you where to create an abstract type that declared each of those operations making them virtual where needed, then you could call eat with different types (that derived from your AMOUNT interface). And it would behave as expected.
I don't work with templates, but I think:
(1) You cannot use templates inside a class, templates are more like global types or global variables.
(2) In O.O.P., the same problem you present, and that you are trying to solve by using templates, can be solved by using inheritance.
Classes work similar to templates, you can extended by adding new things, or replace things of classes with pointers, pointers to objects (A.K.A. "references") and overriding virtual functions.
#include <iostream>
struct Animal {
virtual void eat(int amount ) {
std::cout << "I eat like a generic Animal." << std::endl;
}
virtual ~Animal() { }
};
#if 0
// example 1
struct Wolf : Animal {
virtual void eat(int amount) {
std::cout << "I eat like a wolf!" << std::endl;
}
};
struct Fish : Animal {
virtual void eat(int amount) {
std::cout << "I eat like a fish!" << std::endl;
}
};
#else
// example 2
struct AnimalFood {
virtual int readAmount() { return 5; }
virtual void showName() {
std::cout << "I'm generic animal food" << std::endl;
}
};
struct PredatorFood : AnimalFood {
virtual int readAmount() { return 500; }
virtual void showName() {
std::cout << "I'm food for a predator" << std::endl;
}
};
struct Fish : Animal {
virtual void eat(AnimalFood* aFood) {
if (aFood->readAmount() < 50) {
std::cout << "OK food, vitamines: " << aFood->readAmount() << std::endl;
} else {
std::cout << "too much food, vitamines: " << aFood->readAmount() << std::endl;
}
}
};
struct Shark : Fish {
virtual void eat(AnimalFood* aFood) {
if (aFood->readAmount() < 250) {
std::cout << "too litle food for a shark, Im very hungry, vitamines: " << aFood->readAmount() << std::endl;
} else {
std::cout << "OK, vitamines: " << aFood->readAmount() << std::endl;
}
}
};
struct Wolf : Fish {
virtual void eat(AnimalFood* aFood) {
if (aFood->readAmount() < 150) {
std::cout << "too litle food for a wolf, Im very hungry, vitamines: " << aFood->readAmount() << std::endl;
} else {
std::cout << "OK, vitamines: " << aFood->readAmount() << std::endl;
}
}
};
#endif
int main() {
// find animals
Wolf* loneWolf = new Wolf();
Fish* goldenFish = new Fish();
Shark* sharky = new Shark();
// prepare food
AnimalFood* genericFood = new AnimalFood();
PredatorFood* bigAnimalFood = new PredatorFood();
// give food to animals
loneWolf->eat(genericFood);
loneWolf->eat(bigAnimalFood);
goldenFish->eat(genericFood);
goldenFish->eat(bigAnimalFood);
sharky->eat(genericFood);
sharky->eat(bigAnimalFood);
delete bigAnimalFood;
delete genericFood;
delete sharky;
delete goldenFish;
delete loneWolf;
}
Cheers.