Inheritance and template function c++ - c++

I was wondering if there are pattern/ways to inherit template functions ?
Template functions can not be virtual so if my base class has a template function and my derived class has the same, the function of the base class will always be called in the following example :
struct Base {
Base() {}
template < typename T >
void do_something(T& t) const {
t << "Base" << std::endl ;
}
};
struct Foo : Base {
Foo() : Base () {}
template < typename T >
void do_something(T& t) const {
t << "Foo" << std::endl ;
}
};
struct Bar : Foo {
Bar() : Foo() {}
template < typename T >
void do_something(T& t) const {
t << "Bar" << std::endl ;
}
};
int main(int argc, char** argv)
{
Base *b = new Base() ;
Base *f = new Foo() ;
Base *ba = new Bar() ;
b->do_something(std::cout) ;
f->do_something(std::cout) ;
ba->do_something(std::cout) ;
return 0 ;
}
So this program always print :
Base
Base
Base
Is there a way to make my program print :
Base
Foo
Bar
Actually the only way I found for doing that is to make a static_cast :
...
static_cast<Foo*>(f)->do_something(std::cout) ;
static_cast<Bar*>(ba)->do_something(std::cout) ;
...
Is there any pattern or elegant way to encapsulate the cast so that it will be unnoticeable from the function call ?
Thanks for your replies

You can almost always do what you need by splitting the function into smaller parts, making each part templated if necessary, or virtual if necessary. In this example, that's as simple as:
struct Base {
Base() {}
template < typename T >
void do_something(T& t) const {
t << something_piece() << std::endl ;
}
virtual const char* something_piece() const {
return "Base";
}
};
struct Foo : Base {
Foo() : Base () {}
const char* something_piece() const {
return "Foo";
}
};
struct Bar : Foo {
Bar() : Foo() {}
const char* something_piece() const {
return "Bar";
}
};
It can get more complicated than that, but the idea is pretty powerful at combining compile-time and run-time differences.

Do you have the option to change the struct to a Template class rather than template methods?
If so:
Template<typename T>
struct Base
{
public:
virtual void doSomething();
};
Template<typename T>
struct Foo : Base<T>
{
public:
virtual void doSomething();
};

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

Iterate over different CRTP Derived class methods

In an example below I have a pretty typical CRTP example, two different derived classes that both have a method bar. The base class has a method foo which just forwards to some derived bar method
#include <iostream>
template<typename Derived>
class Base {
public:
void foo() {
static_cast<Derived*>(this)->bar();
}
};
class DerivedA : public Base<DerivedA> {
public:
void bar() {
::std::cout << "A\n";
}
};
class DerivedB : public Base<DerivedB> {
public:
void bar() {
::std::cout << "B\n";
}
};
int main() {
DerivedA a;
DerivedB b;
a.foo();
b.foo();
}
It doesn't seem like I can have an array / vector / etc. of the base class because it would have to have a type along the lines of Base<T> where T is different
Is there some kind of convention without virtual for being able to iterate over different derived classes assuming they all have the same method (bar in this case)?
You can use Boost.Variant. For example:
typedef boost::variant<DerivedA, DerivedB> Derived;
struct BarCaller : public boost::static_visitor<void> {
template <class T>
void operator()(T& obj) {
obj.bar();
}
};
int main() {
std::vector<Derived> vec{DerivedA(), DerivedB(), DerivedA()};
BarCaller bar;
for (Derived& obj : vec) {
obj.apply_visitor(bar);
}
}
This lets you store heterogeneous types in a vector or other STL container (by using a "discriminated union"), and lets you call a specific function on all of them regardless of their not having a common ancestor or any virtual methods.
It doesn't seem like I can have an array / vector / etc. of the base class because it would have to have a type along the lines of Base<T> where T is different.
You can have a base class of Base<T> for all T, then, you can have a list/vector/array of pointers to the base class, if that works for you.
struct BaseOne
{
virtual void foo() = 0;
virtual ~BaseOne() {}
};
template<typename Derived>
class Base : struct BaseOne {
public:
void foo() {
static_cast<Derived*>(this)->bar();
}
};
and then,
int main() {
std::vector<BaseOne*> v {new DerivedA, new DerivedB };
for ( auto item : v )
item->bar();
for ( auto item : v )
delete item;
}
Is there some kind of convention without virtual for being able to iterate over different derived classes assuming they all have the same method (bar in this case)?
No, there isn't.
As per now, variant has became part of the C++17 standard and the solution to the problem can be solved by std::variant and std::visit as follows.
The template class in the example is Interface<> and use the CRTP idiom to force derived class to implement helloImpl():
#include <iostream>
#include <vector>
#include <variant>
template<typename Implementer>
struct Interface {
void hello() const {
static_cast<Implementer const *>(this)->helloImpl();
}
};
A couple of class examples with different implementations of helloImpl()
struct Hello1 : public Interface<Hello1> {
void helloImpl() const {
std::cout << "Hello1" << std::endl;
}
};
struct Hello2 : public Interface<Hello2> {
void helloImpl() const {
std::cout << "Hello2" << std::endl;
}
};
And here is how to use it to store data in a vector<> container and its traversal:
int main() {
using var_t = std::variant<Hello1, Hello2>;
std::vector<var_t> items{Hello1(), Hello1(), Hello2()};
for(auto &item: items) {
std::visit([](auto &&arg) {
arg.hello();
}, item);
}
return 0;
}

Polymorphic function call without duplicate code

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

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

Override virtual function through CRTP base class

Old: How can I override a virtual function through a CRTP base class?
struct I { virtual void foo() = 0; };
template<class D>
struct B { void foo() { } }; // provides implementation of foo in D
struct D : I, B<D> { }; // D has an implementation of foo that should override I
int main() { D d; }
Error: unimplemented pure virtual method 'foo' in 'D'
Simpler: How can I override a virtual function without reimplementing it in a derived type? (I guess this question goes against the definition of a virtual function).
struct I { virtual void foo() = 0; };
struct B { void foo() { } };
struct D : B, I { };
int main() { D d; }
Besides the obvious but clunky void foo() { B::foo(); } solution, you could separate the "implements a foo" interface from the more complete interface I:
struct FooInterface {
virtual ~FooInterface() {}
virtual void foo() = 0;
};
struct I : public virtual FooInterface {};
template<class D>
struct B : public virtual FooInterface { void foo() { } };
struct D : I, B<D> {};
int main() { D d; }
You can implement D::foo() as a trivial wrapper calling B<D>::foo(). If you have a lot of places that would need to do this, you could make a macro to help out, like:
#define WRAP(CLASS, METHOD) \
METHOD() { return CLASS::METHOD(); }
struct D : I, B<D>
{
void WRAP(B<D>, foo);
};
you're needlessly mixing two different concepts: crtp, and inheriting an implementation of a virtual function
crtp is used for compile time polyrmorphism, virtual functions for runtime polymorphism
that said, you can inherit in an implementation of a virtual function by way of dominance in a virtual inheritance hierarchy, which yields roughly the effect of java/c# implementation inheritance
example:
struct tutti_i
{
virtual int frutti() const = 0;
};
struct tutti_impl_1
: virtual tutti_i
{
int frutti() const override { return 42; }
};
struct base
: virtual tutti_i
{};
struct derived
: base
, tutti_impl_1
{};
#include <iostream>
int main()
{
tutti_i&& tutti = derived();
std::cout << tutti.frutti() << std::endl;
}
For those who don't care whether or not B inherits from I, you can also implement this with CRTP as originally asked:
struct I { virtual void foo() = 0; };
template <class D>
struct B : I { void foo(){ /* Do something fancy with D's type */ } };
struct D : B<D> { };
And if you need further inheritance so that the implementation of foo is always of the most-derived type, you can introduce an intermediate type to disambiguate which implementation of foo gets used:
struct I { virtual void foo() = 0; };
template <class T>
struct B : virtual I { void foo() { /* Do something fancy with the most-derived type */ }};
struct D : B<D> { };
template <typename Base, typename Derived>
struct InheritFrom : public Base, public B<D> { void foo() { B<D>::foo(); } };
struct FurtherDerived : InheritFrom<D, FurtherDerived> { };