Polymorphic function call without duplicate code - c++

Suppose that all classes of a hierarchy implement a template member function g. All classes share the same implementation of two other functions f1 and f2 that call this template:
struct A {
virtual void f1() {
g(5);
}
virtual void f2() {
g(5.5);
}
private:
template <typename T> void g(T) {std::cout << "In A" << std::endl;}
};
struct B: A {
// Can I get rid of this duplicate code?
virtual void f1() {
g(5);
}
virtual void f2() {
g(5.5);
}
private:
template <typename T> void g(T) {std::cout << "In B" << std::endl;}
};
struct C: A {
// Can I get rid of this duplicate code?
virtual void f1() {
g(5);
}
virtual void f2() {
g(5.5);
}
private:
template <typename T> void g(T) {std::cout << "In C" << std::endl;}
};
int main()
{
B b;
A &a = b;
a.f1();
return 0;
}
Since the implementations of f1 and f2 are identical in all the classes, how can I get rid of the duplicate code and still have the polymorphic call in main work as expected (i.e produce the output "In B")?

Note that the implementations of f1 and f2 in A, B, and C are not identical. Let's restrict it to f1s. One calls a function named ::A::g<int>, another one calls a function named ::B::g<int>, and the third one calls a function named ::C::g<int>. They are very far from identical.
The best you could do is have a CRTP-style base:
template <class Derived>
struct DelegateToG : public A
{
void f1() override
{
static_cast<Derived*>(this)->g(5);
}
void f2() override
{
static_cast<Derived*>(this)->g(5.5);
}
};
class B : public DelegateToG<B>
{
friend DelegateToG<B>;
private:
template <class T> void g(T) { /*...*/ }
};
class C : public DelegateToG<C>
{
friend DelegateToG<C>;
private:
template <class T> void g(T) { /*...*/ }
};

You can just factor out the class-specific things that the template function uses, such as (in your example) the class name:
#include <iostream>
using namespace std;
class A
{
private:
virtual auto classname() const -> char const* { return "A"; }
protected:
template <typename T> void g(T) {cout << "In " << classname() << endl;}
public:
virtual void f1() { g(5); }
virtual void f2() { g(5.5); }
};
class B
: public A
{
private:
auto classname() const -> char const* override { return "B"; }
};
class C
: public A
{
private:
auto classname() const -> char const* override { return "C"; }
};
auto main()
-> int
{ static_cast<A&&>( B() ).f1(); }

Related

Virtual template workaround without too much verbosity

I am looking for a workaround to the lack of virtual template functions in C++.
What I want ideally is to be able to store my derived classes in a vector, iterate over those and call the correct function, so in pseudo-code:
template<typename T>
struct Output
{
...
};
struct Base
{
template<typename T>
virtual void doSomething(Output<T>& out) = 0;
};
struct DerivedA : public Base
{
DerivedA(const char* filename) {...}
template<typename T>
void doSomething(Output<T>& out) final
{
...
}
};
struct DerivedB : public Base
{
DerivedB(const char* filename) {...}
template<typename T>
void doSomething(Output<T>& out) final
{
...
}
};
int main()
{
std::vector<Base*> vec;
vec.push_back(new DerivedA("data1.bin"));
vec.push_back(new DerivedB("data2.bin"));
vec.push_back(new DerivedA("data3.bin"));
vec.push_back(new DerivedA("data4.bin"));
Output<float> outF;
Output<double> outD;
Output<int> outI;
for (auto e : vec)
{
e->doSomething(outF);
e->doSomething(outD);
e->doSomething(outI);
}
return 0;
}
I would prefer it if the workaround is as "painless" and non-verbose as possible (since I am using the templates to avoid redefining the same function n times for n different types in the first place). What I had in mind was making myself a vtable with std::map, and doing some dynamic_casts. I am looking for any better ideas, or even for a concise implementation of that idea if you consider it the best in this scenario. I am looking for a solution that is ideally the least intrusive, and that is very easy to add new classes to.
Edit:
I figured a workaround, but it includes some verbosity (but at least avoids non-trivial code duplication):
struct Base
{
virtual void doSomething(Output<int>& out) = 0;
virtual void doSomething(Output<float>& out) = 0;
virtual void doSomething(Output<double>& out) = 0;
private:
template<typename T>
void doSomething(Output<T>& out)
{
std::cout << "Base doSomething called with: " << typeid(T).name() << "\n";
}
};
struct DerivedA : public Base
{
void doSomething(Output<int>& out) final
{
doSomething<int>(out);
}
void doSomething(Output<float>& out) final
{
doSomething<float>(out);
}
void doSomething(Output<double>& out) final
{
doSomething<double>(out);
}
private:
template<typename T>
void doSomething(Output<T>& out)
{
std::cout << "DerivedA doSomething called with: " << typeid(T).name() << "\n";
}
};
struct DerivedB : public Base
{
void doSomething(Output<int>& out) final
{
doSomething<int>(out);
}
void doSomething(Output<float>& out) final
{
doSomething<float>(out);
}
void doSomething(Output<double>& out) final
{
doSomething<double>(out);
}
private:
template<typename T>
void doSomething(Output<T>& out)
{
std::cout << "DerivedB doSomething called with: " << typeid(T).name() << "\n";
}
};
Does anybody have any better idea how I can go about this without having to redefine the same functions over and over? Ideally it would be defined once in the base class, CRTP doesn't seem to help. Dynamic casts seem like the other sane option.
Try something like this:
struct OutputBase
{
virtual void doSomething() = 0;
};
template<class T >
struct Output : public OutputBase
{
virtual void doSomething()
{
std::cout << typeid(T).name();
}
};
struct Base
{
virtual void doSomething(OutputBase* out) = 0;
};
struct DerivedA : public Base
{
virtual void doSomething(OutputBase* out)
{
std::cout << "DerivedA doSomething called with: ";
out->doSomething();
std::cout<< std::endl;
}
};
struct DerivedB : public Base
{
virtual void doSomething(OutputBase* out)
{
std::cout << "DerivedB doSomething called with: ";
out->doSomething();
std::cout << std::endl;
}
};
int main()
{
OutputBase* out_int = new Output < int > ;
OutputBase* out_double = new Output < double >;
Base* a = new DerivedA;
a->doSomething(out_int);
a->doSomething(out_double);
Base* b = new DerivedB;
b->doSomething(out_int);
b->doSomething(out_double);
return 0;
}
You can use a wrapper around Output if you don't want to change it.

Putting virtual functions into a family

Given
class A {
public:
virtual int foo (int) const = 0;
virtual void bar (char, double) const = 0;
};
class B : public A {
virtual int foo (int) const {std::cout << "B::foo() called.\n"; return 3;}
virtual void bar () const {std::cout << "B::bar() called.\n";}
};
class C : public B {
virtual int foo (int) const {std::cout << "C::foo() called.\n"; return 8;}
virtual void bar (char, double) const {std::cout << "C::bar() called.\n";}
};
I want to put foo and bar (and other virtual functions of A) into a template family of functions. Here's what I came up with so far:
#include <iostream>
enum Enum {Foo, Bar};
template <Enum> struct EnumTraits;
template <> struct EnumTraits<Foo> { using return_type = int; };
template <> struct EnumTraits<Bar> { using return_type = void; };
class A {
template <Enum> class Execute;
public:
virtual int foo (int) const = 0;
virtual void bar (char, double) const = 0;
template <Enum E, typename... Args>
typename EnumTraits<E>::return_type execute(Args&&... args) const {
return Execute<E>(this)(std::forward<Args>(args)...);
}
};
template <>
class A::Execute<Foo> {
const A* a;
public:
Execute (const A* a_) : a(a_) {}
template <typename... Args>
int operator()(Args&&... args) const {return a->foo(std::forward<Args>(args)...);}
};
template <>
class A::Execute<Bar> {
const A* a;
public:
Execute (const A* a_) : a(a_) {}
template <typename... Args>
void operator()(Args&&... args) const {a->bar(std::forward<Args>(args)...);}
};
class B : public A {
virtual int foo (int) const {std::cout << "B::foo() called.\n"; return 3;}
virtual void bar () const {std::cout << "B::bar() called.\n";}
};
class C : public B {
virtual int foo (int) const {std::cout << "C::foo() called.\n"; return 8;}
virtual void bar (char, double) const {std::cout << "C::bar() called.\n";}
};
int main() {
A* c = new C;
int n = c->foo(5); // C::foo() called.
c->bar(3, 'c'); // C::bar() called.
n = c->execute<Foo>(5); // C::foo() called.
c->execute<Bar>(3, 'c'); // C::bar() called.
}
But the specializations A::Execute<Foo> and A::Execute<Bar> look near-identical and should ideally be left unspecialized (especially if there are many other virtual functions than foo and bar). Written something like:
template <Enum N>
class A::Execute {
const A* a;
public:
Execute (const A* a_) : a(a_) {}
template <typename... Args>
int operator()(Args&&... args) const {return a->???(std::forward<Args>(args)...);}
};
How to fill in that ??? part? Ideally, I was hoping to use the EnumTraits class already present.
Here's my attempt. I have replaced the enum by structs that are used as tags and EnumTraits by TagTraits. I prefer the struct approach since it allows for new tags to be added without affecting the existing tags.
#include <iostream>
#include <functional>
template <typename T> struct TagTraits;
// Generic implementation of A based on TagTraits.
class A {
template <typename Tag, typename... Args>
class Execute {
const A* a;
public:
Execute (const A* a_) : a(a_) {}
typename TagTraits<Tag>::return_type operator()(Args&&... args) const
{
return (a->*(TagTraits<Tag>::get_funtion_ptr()))(std::forward<Args>(args)...);
}
};
public:
virtual int foo (int) const = 0;
virtual void bar (char, double) const = 0;
template <typename Tag, typename... Args>
typename TagTraits<Tag>::return_type execute(Args&&... args) const
{
return Execute<Tag, Args...>(this)(std::forward<Args>(args)...);
}
};
// tag for foo and the corresponding TagTraits
struct foo_tag {};
template <> struct TagTraits<foo_tag>
{
using return_type = int;
static decltype(&A::foo) get_funtion_ptr(){ return &A::foo;}
};
// tag for bar and the corresponding TagTraits
struct bar_tag {};
template <> struct TagTraits<bar_tag>
{
using return_type = void;
static decltype(&A::bar) get_funtion_ptr(){ return &A::bar;}
};
// Derived classes of A.
class B : public A {
virtual int foo (int) const {std::cout << "B::foo() called.\n"; return 3;}
virtual void bar (char, double) const {std::cout << "B::bar() called.\n";}
};
class C : public B {
virtual int foo (int) const {std::cout << "C::foo() called.\n"; return 8;}
virtual void bar (char, double) const {std::cout << "C::bar() called.\n";}
};
// Test B
void test_B()
{
A* aPtr = new B;
int n = aPtr->foo(5); // B::foo() called.
aPtr->bar(3, 'c'); // B::bar() called.
n = aPtr->execute<foo_tag>(5); // B::foo() called.
aPtr->execute<bar_tag>(3, 'c'); // B::bar() called.
}
// Test C
void test_C()
{
A* aPtr = new C;
int n = aPtr->foo(5); // C::foo() called.
aPtr->bar(3, 'c'); // C::bar() called.
n = aPtr->execute<foo_tag>(5); // C::foo() called.
aPtr->execute<bar_tag>(3, 'c'); // C::bar() called.
}
int main()
{
test_B();
test_C();
}
Output:
B::foo() called.
B::bar() called.
B::foo() called.
B::bar() called.
C::foo() called.
C::bar() called.
C::foo() called.
C::bar() called.
You cannot combine inheritance and polymorphism with template metaprogramming. What you are trying to do is use compile time mechanisms to call the right functions. While that is possible you cannot dereference a pointer to call the right function and expect that to run in compile time.
Essentially what you have done is wrap in the inheritance hierarchy a hierarchy of partial template specializations. That's a little confusing. If you dereference a pointer that has an inheritance hierarchy the call will get resolved by lookup in the virtual table.
You can pull of template compile time dispatch too, but that would be a little different. You would need to use SFINAE to create an interface and work from there

Is a C++ template able to "forward any class function" from parent class?

class Foo {
public:
void methodA();
};
class ManagedFoo {
Foo fooInst;
public:
void methodA() { doSomething(); fooInst.methodA();}
};
Now I want to make ManagedFoo as a template, managing any class not only Foo, and before any of Foo's function is called, call doSomething first.
template<typename _TyManaged>
class Manager {
_TyManaged _managedInst;
void doSomething();
public:
/*Forward every function called by _managedInst*/
/*How to write this?*/
};
I want to make it the same, make it replaceable between this two class, like this :
Foo* foo = new Foo();
foo->methodA();
Manager<Foo> managedFoo = new Manager<Foo>();
managedFoo->methodA(); //Hope it call Manager::doSomething() first then call _managedInst.methodA();
Can C++11 template do such thing? if answer is yes, how to?
Solution based on operator-> overloading:
#include <iostream>
#include <memory>
class A {
public:
void foo() { std::cout << "foo\n"; }
void bar() { std::cout << "bar\n"; }
};
template <typename T>
class ManagedBase {
std::shared_ptr<T> _inst;
public:
ManagedBase(const std::shared_ptr<T> inst) : _inst(inst) { }
virtual ~ManagedBase() { }
std::shared_ptr<T> operator->() {
before();
return this->_inst;
}
virtual void before() =0;
};
template <typename T>
class ManagedPrint : public ManagedBase<T> {
public:
ManagedPrint(const std::shared_ptr<T> inst) : ManagedBase(inst) { }
virtual void before() {
std::cout << "Said: ";
}
};
int main() {
auto ma = ManagedPrint<A>(std::make_shared<A>());
ma->bar(); // Said: foo
ma->bar(); // Said: bar
}
Something like this?
template<typename _TyManaged>
class Manager {
_TyManaged _managedInst;
void doSomething();
public:
_TyManaged* operator->() {
doSomething();
return &_managedInst;
}
};
This can solve your problem. But I'm still not sure what you want to do with your Manager class.
class Foo {
public:
void methodA();
};
template<typename T>
class ManagedFoo : public T {
public:
// some further extensions
};
And of course in this way you change the semantic of the Foo class by the manager from:
It has a
to
It is a
So I'm not sure if this is true in your case.

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

Error with member function template

I am getting compilation error in below code.
class A
{
public:
A()
{
}
~A()
{
}
void func()
{
cout <<"Ha ha ha \n";
}
};
class C
{
public:
C()
{
}
~C()
{
}
template<typename type> func()
{
type t;
t.func();
}
void callme()
{
func<A>();
}
};
VC6 doesn't support member function templates. You actually have several solutions:
Move func() out of the class definition
template<typename type> void func()
{
type t;
t.func();
}
or rewrite callme()
void callme()
{
A a;
a.func();
}
or use class template
class C
{
public:
template<class T> struct func
{
void operator()()
{
T t;
t.func();
}
};
void callme()
{
func<A>()();
}
};
The definition of func<T>() doesn't specify its return type, which is invalid in C++.
It should be:
template<typename type> void func()
{
type t;
t.func();
}