Say I've got the following (pseudo-)code:
class base{
public:
virtual void callMe() = 0;
virtual void doRender() = 0;
}
class a : public base{
public:
virtual void callMe(){/*doA*/} override;
}
class b : public base{
public:
virtual void callMe(){/*doB*/} override;
}
class myClass : public base, public a, public b{
public:
virtual void doRender(){
this->a::callMe();
this->b::callMe();
} override;
}
Would there be a way to write this differently? Something like:
class myClass : public base, public a, public b{
public:
virtual void doRender(){
this->allSupers::callMe();
} override;
}
My goal with this would be to have a base class that can be extended to have different "features", all of which have to be executed on doRender.
I know I could of course keep track of these functions by means of a function pointer list in base, in which the subclasses put their own functions when constructed, but I'd like to avoid that. Having to iterate over these functions still gives me at least three lines of code in my final doRender. (Or one long unreadable line.)
I'm open for suggestions using templates.
Depending on you actual problem at hand, you might be able to use the mixin-style. Essentially you can have each class call the next callMe at the end (or begining) of their own callMe. One benefit is that callMe does not need to be a virtual function. Here is a minimal example (online):
#include <iostream>
class base
{
public:
void callMe() {}; // Empty base case
virtual void doRender() = 0;
};
template <class super>
class a : public super
{
public:
void callMe()
{
std::cout << "doA" << '\n';
super::callMe(); // Call the next
};
};
template <class super>
class b : public super
{
public:
void callMe()
{
std::cout << "doB" << '\n';
super::callMe(); // Call the next
};
};
template <class super>
class myClass_t : public super
{
public:
void doRender()
{
super::callMe();
};
};
using myClass = myClass_t<a<b<base> > >; // Defining the order of evaluation;
int main()
{
myClass m;
m.doRender();
}
With variadic template, you may do:
template <typename ... Ts>
class myClassTs : public base, public Ts...
{
public:
virtual void doRender(){
int dummy[] = {0, (Ts::callMe(), void(), 0)...};
static_cast<void>(dummy); // Silent warning for unused variable
} override;
}
using myClass = myClassTs<a, b>;
And in C++17, it would be
template <typename ... Ts>
class myClassTs : public base, public Ts...
{
public:
virtual void doRender(){
(static_cast<void>(Ts::callMe()), ...);
} override;
}
Related
My starting situation where I don't know what type to use in Base class:
class Base {
private:
virtual void doSomethingSpecific(?type param) = 0;
public:
// this function uses doSomethingSpecific
void doSomething() {...}
};
class Derived1 : public Base {
private:
void doSomethingSpecific(Derived1Type param) override;
};
class Derived2 : public Base {
private:
void doSomethingSpecific(Derived2Type param) override;
};
My solution using templates:
template<typename DerivedType>
class Base {
private:
virtual void doSomethingSpecific(DerivedType param) = 0;
public:
// this function uses doSomethingSpecific
void doSomething() {...}
};
class Derived1 : public Base<Derived1Type> {
private:
void doSomethingSpecific(Derived1Type param) override;
};
class Derived2 : public Base<Derived2Type> {
private:
void doSomethingSpecific(Derived2Type param) override;
};
This works, but I am posting this because it feels like this my not be the most optimal/straightforward approach? Also even though the header files are simple, templates significantly increased compile time.
Here is a more specific example of how I use doSomethingSpecific function:
template<typename DerivedType>
class Base {
std::vector<DerivedType> components;
private:
virtual void doSomethingSpecific(DerivedType param) = 0;
public:
Base(std::vector<DerivedType> components) {
this->components = components;
}
// this function uses doSomethingSpecific
void doSomething() {
doSomethingSpecific(components[0]);
}
};
class Derived1 : public Base<Derived1Type> {
private:
void doSomethingSpecific(Derived1Type param) override;
};
int main() {
std::vector<Derived1Type> components = {...};
Derived1 obj(components);
obj.doSomething();
}
I do not understand the first example of your code. It is not clear why there is public inheritance and a virtual method. In the second example it is apparent there there is no need for the virtual method. Base<A> and Base<B> are two unrelated types. Consequently Derived1 and Derived2 do not share a common base. There is no runtime polymorphism.
For compile time polymorphism you can employ the CRTP (curiously recurring template pattern). Your code looks already very similar. The major change I had to make is to remove the overriding (its not needed):
#include <iostream>
template<typename T>
struct Base {
void doSomething() {
static_cast<T*>(this)->doSomethingSpecific(typename T::type{});
}
};
struct Derived1 : public Base<Derived1> {
using type = int;
void doSomethingSpecific(type param) { std::cout << "hello int " << param; }
};
struct Derived2 : public Base<Derived2> {
using type = double;
void doSomethingSpecific(type param) { std::cout << "hello double " << param; }
};
int main() {
Derived1{}.doSomething();
Derived2{}.doSomething();
}
Live Demo
I also added a member alias type that Base can use to construct the parameter to pass to the methods. And for CRTP to work the base must be parametrized on the deriving class.
Again: Derived1 and Derived2 do not share a common base (as was the case already in your code).
let's say I have the following classes:
class Base {
public:
virtual int do_something() = 0;
protected:
virtual int give_intermediate_result(int) = 0;
int m_some_shared_resources;
};
class Foo : public Base {
public:
virtual int do_something() override { return give_intermediate_result(1); }
protected:
virtual int give_intermediate_result(int a) override { return a*2; }
};
// and something like this:
class FooMixinA : public virtual Base {
protected:
virtual int give_intermediate_result(int) override;
};
class FooMixinB : public virtual Base {
public:
virtual int do_something() override;
};
What I would like to do is something like this:
Foo<FooMixinA, FooMixinB> myfoo (...);
which basically should override Foo's implementation of do_something with that of FooMixinB and give_intermediate_result with that of FooMixinA. Additionally I want mixins to be able to replace other mixins functionality, i. e. the order of the mixins is important as one mixin may use (f. e. the get_intermediate_result of) another mixin.
At the same time they should all have access to some shared underlying resource.
Can I do something like that and if so how would I approach it?
template<class Base, template<class>class...Mixins>
struct Foo:Base{};
template<class Base, template<class>class M0, template<class>class...Mixins>
struct Foo<Base, M0, Mixins...>:M0<Foo<Base, Mixins...>>{};
struct Base{
virtual int A()=0;
virtual int B()=0;
virtual ~Base()=default;
};
template<class Base>
struct MixinA:Base{
int A() final{ return 3; }
};
template<class Base>
struct MixinB:Base{
int B() override{ return -1; }
};
template<class Base>
struct MixinB2:Base{
int B() final{ return 0; }
};
using Bob=Foo<Base, MixinA, MixinB2, MixinB>;
std::unique_ptr<Base> pBase=std::make_unique<Bob>();
std::cout << pBase->A() << pBase->B() <<'\n';
Leftmost mixins override rightmost ones here.
For the other way around
template<class Base, template<class>class M0, template<class>class...Mixins>
struct Foo<Base, M0, Mixins...>:Foo<M0<Base>, Mixins...>{};
We can remove the Base argument of Foo if you really want. For right-to-left application:
template<template<class>class...Mixins>
struct Foo:Base{};
template<template<class>class M0, template<class>class...Mixins>
struct Foo<M0, Mixins...>:M0<Foo<Mixins...>>{};
it is easy. For left-to-right, you need to get fancier.
I have several disparate templated pure abstract classes. I derive from these to get a bunch of classes, and from there, I can use those to make a bunch of objects. I would like to put all of these objects into a container. However, they are all of different types. I am wondering how to accomplish this late-stage polymorphism.
Say this is my pre-existing code that I have right now:
#include <iostream>
template<typename T>
class A{
public:
A() : m_num(1.0) {};
virtual ~A() {};
virtual void printNum() const = 0;
protected:
T m_num;
};
template<typename T>
class B{
public:
B() : m_num(2.0) {};
virtual ~B() {};
virtual void printTwiceNum() const = 0;
protected:
T m_num;
};
class A_example : public A<int>
{
public:
A_example() : A<int>() {};
void printNum() const { std::cout << m_num << "\n"; };
};
class B_example : public B<int>
{
public:
B_example() : B<int>() {};
void printTwiceNum() const { std::cout << 2*m_num << "\n"; };
};
int main(){
A_example first;
B_example second;
first.printNum();
second.printTwiceNum();
return 0;
}
With more classes, it could get pretty messy inside of main(). Ideally I could jut iterate over the container and call print() on each element. My first thought is to use a std::vector<unique_ptr<Base>>. This seems to work:
#include <iostream>
#include <vector> // new include
#include <memory> // new include
#include <utility> // new include
// new Base class here
class Base{
public:
virtual ~Base(){};
};
template<typename T>
class A : public Base{ // new inheritance here
public:
A() : m_num(1.0) {};
virtual ~A() {};
virtual void printNum() const = 0;
protected:
T m_num;
};
template<typename T>
class B : public Base{ // new inheritance here as well
public:
B() : m_num(2.0) {};
virtual ~B() {};
virtual void printTwiceNum() const = 0;
protected:
T m_num;
};
class A_example : public A<int>
{
public:
A_example() : A<int>() {};
void printNum() const { std::cout << m_num << "\n"; };
};
class B_example : public B<int>
{
public:
B_example() : B<int>() {};
void printTwiceNum() const { std::cout << 2*m_num << "\n"; };
};
int main(){
std::vector<std::unique_ptr<Base>> v;
v.emplace_back( new A_example() );
v.emplace_back( new B_example() );
//v[0]->printNum(); // nope
//v[1]->printTwiceNum(); // nope
return 0;
}
This is cool because I didn't have to change A_example or B_example, and all I changed in A and B was that I added : public Base. However, I have no idea how to call each elements print*** function. Is there any way to call the printNum() and printTwiceNum() functions, and for them to be automatically recognized?
The simplest approach is to just make a virtual function Base::print and have your derived classes implement it. But that's not always appropriate.
Another approach is to branch on dynamic_cast conversions. The premise there is that some functions are only available on some classes. But this can get hairy especially when using class templates, as you must handle all expected template parameters.
To generalize this, you can use interface classes. Let's say you have lots of different classes but only a small number of print variations. In that case, it may make sense to do this:
class PrintNumInterface {
public:
virtual void printNum() const = 0;
};
class PrintTwiceNumInterface {
public:
virtual void printTwiceNum() const = 0;
};
template<typename T> class A : public Base, public PrintNumInterface { ... };
template<typename T> class B : public Base, public PrintTwiceNumInterface { ... };
And now, no matter how many additional classes or template expansions you have to deal with, you only need to handle these interfaces:
for (auto& p : v)
{
if (PrintNumInterface* iface = dynamic_cast<PrintNumInterface*>(p.get())
iface->printNum();
else if (PrintTwiceNumInterface* iface = dynamic_cast<PrintTwiceNumInterface*>(p.get())
iface->printTwiceNum();
}
How to do multiple inheritance just for function?
must share data of the base class
no virtual function (assume that vtable is expensive)
avoid virtual inheritance
implementation must be able to reside in .cpp
c++14 is allowed
Here are similar questions :-
Multiple inheritance in diamond shape with functions only - use virtual inheritance. Virtual inheritance is generally bad and expensive.
multiple inheritance without virtual inheritance - focuses on syntax and compiling rather than programming technique.
Multilevel inheritance in c++ (CRTP) , CRTP and multilevel inheritance , Eliminate redundancy with CRTP and multiple inheritance (C++03) and Using CRTP with virtual inheritance - implementation must be in header
Here is a sample code (coliru demo) :-
class O{
protected: int database=0;
};
class A : public O{
public: void print(){
std::cout<<database<<std::endl;
}
};
class B : public O{
public: void set(int s){
database=s+1;
}
};
class AB : public O{
public: void print(){//duplicate
std::cout<<database<<std::endl;
}
public: void set(int s){//duplicate
database=s+1;
}
};
//AB ab; ab.set(1); ab.print(); // would print 2
Here is my attempt (wandbox demo). I abuse CRTP :( :-
class O{
public: int database=0;
};
template<class T>class OA{
public: void print(){
std::cout<<static_cast<T*>(this)->database<<std::endl;
}
};
template<class T>class OB{
public: void set(int s){
static_cast<T*>(this)->database=s+1;
}
};
class A :public O,public OA<A>{};
class B :public O,public OB<B>{};
class AB :public O,public OA<AB>,public OB<AB>{};
It works, but it looks inelegant.
Furthermore, implementation must be in header (because OA and OB are template classes).
Are there better approaches? Or is this the way to go?
Sorry if it is too newbie question or already asked. I am a C++ beginner.
Edit
Give extended example of using please.
In ECS, it would be useful in some cases :-
class O{
protected: EntityHandle e;
};
class ViewAsPhysic : public O{ //A
public: void setTransform(Transformation t){
Ptr<PhysicTransformComponent> g=e;
g->transform=t;
}
};
class ViewAsLight : public O{ //B
public: void setBrightness(int t){
Ptr<LightComponent> g=e;
g->clan=t;
}
};
class ViewAsLightBlock : public O{ //AB
//both functions
};
The problem here is that the database field is member of class O. So without virtual inheritance, A and B will have each their own copy of database. So you must find a way to force A and B to share same value. You could for example use a reference field initialized in a protected constructor:
#include <iostream>
class O{
int _db;
protected: int &database;
O(): database(_db) {};
O(int &db): database(db) {};
};
class A : public O{
public: void print(){
std::cout<<database<<std::endl;
}
A() {} // public default ctor
protected: A(int& db): O(db) {}; // protectect ctor
};
class B : public O{
public: void set(int s){
database=s+1;
}
B() {} // public default ctor
protected: B(int& db): O(db) {}; // protectect ctor
};
class AB : public A, public B {
int _db2;
public: AB(): A(_db2), B(_db2) {}; // initialize both references to same private var
};
int main() {
AB ab;
ab.set(1);
ab.print();
return 0;
}
displays as expected:
2
Above code uses no virtual inheritance, no virtual function and no templates, so method can safely implemented in cpp files. The class AB actually uses methods from its both parents and has still a coherent view on its underlying data. In fact it simulates an explicit virtual inheritance by building the common data in the most derived class and injecting in through protected constructors in its parents.
Something like this?
must share data of the base class - check
no virtual function (assume that vtable is expensive) - check
avoid virtual inheritance - check
implementation must be able to reside in .cpp- check
c++14 is allowed - check. c++11 used.
#include <iostream>
class O {
protected:
int database = 0;
};
/*
* the concept of implementing print for a base class
*/
template<class...Bases>
struct implements_print : Bases... {
void print() const {
std::cout << this->database << std::endl;
}
};
/*
* The concept of implementing set for a base class
*/
template<class...Bases>
struct implements_set : Bases... {
void set() {
++this->database;
}
};
struct B : implements_set<O> {
};
struct A : implements_print<O> {
};
struct AB : implements_set<implements_print<O>> {
};
int main() {
A a;
a.print();
B b;
b.set();
AB ab;
ab.set();
ab.print();
}
Another way, using composition and an access class to provide access to the protected member. This example shows how to defer the work on database to another compilation unit:
#include <iostream>
/*
* this stuff in cpp
*/
namespace implementation
{
void print(const int& database) {
std::cout << database << std::endl;
}
void set(int& database) {
++database;
}
}
/*
* this stuff in header
*/
struct OAccess;
class O {
private:
int database = 0;
friend OAccess;
};
struct OAccess {
template<class Host>
constexpr decltype(auto) database(Host &host) const { return (host.database); } // note: () makes reference
template<class Host>
constexpr decltype(auto) database(Host const &host) const { return (host.database); } // note: () makes reference
};
/*
* the concept of implementing print for a derived class
*/
template<class Host>
struct implements_print {
void print() const {
OAccess access;
implementation::print(access.database(self()));
}
private:
decltype(auto) self() const { return static_cast<Host const &>(*this); }
};
/*
* The concept of implementing set for a derived class
*/
template<class Host>
struct implements_set {
void set() {
OAccess access;
implementation::set(access.database(self()));
}
private:
decltype(auto) self() { return static_cast<Host &>(*this); }
};
template<template<class> class...Impls>
struct OImpl : Impls<OImpl<Impls...>> ..., O {
};
using B = OImpl<implements_set>;
using A = OImpl<implements_print>;
using AB = OImpl<implements_print, implements_set>;
int main() {
A a;
a.print();
B b;
b.set();
AB ab;
ab.set();
ab.print();
}
We start with defining the concepts of things that can print and things that can be set:
namespace util {
template<class Base, class Derived, class R=void>
using if_base = std::enable_if_t< std::is_base_of< std::decay_t<Base>, std::decay_t<Derived>>::value, R >;
struct stub {};
}
namespace concepts {
template<class Token>
void do_print(Token, util::stub const&)=delete;
template<class Token>
void do_set(Token, util::stub&, int)=delete;
struct has_print {
struct token { friend struct has_print; private: token(int){} };
template<class T>
friend util::if_base<has_print, T> print(T const& t) {
do_print(get_token(), t);
}
private: static token get_token() { return 0; }
};
struct has_set {
struct token { friend struct has_set; private: token(int){} };
template<class T>
friend util::if_base<has_set, T> set(T& t, int x) {
do_set(get_token(),t, x);
}
private: static token get_token() { return 0; }
};
}
We then declare O and the operations you can support on it:
namespace DB {
class O;
void do_print(::concepts::has_print::token, O const& o);
void do_set(::concepts::has_set::token, O& o, int);
class O{
protected: int database=0;
friend void do_print(::concepts::has_print::token, O const&);
friend void do_set(::concepts::has_set::token, O&, int);
};
class A : public O, public concepts::has_print {
};
class B : public O, public concepts::has_set {
};
class AB : public O, public concepts::has_print, concepts::has_set {
};
}
void DB::do_print(::concepts::has_print::token, O const& o ) { std::cout << o.database << std::endl; }
void DB::do_set(::concepts::has_set::token, O& o, int x) { o.database = x+1; }
The hard part of this is the access control.
I ensure it isn't possible to call do_set except through has_set::set.
That is what all those tokens are about. You can strip them out and their overhead if you are willing to just say "don't call the do_ functions" (and maybe give them another name, like private_impl_set).
Live example.
To start discussion.
class O
{
// no virtual destructor. So cant use polymorphic deletion
// like :
// O *o = new AB;
// delete o;
protected: int database=0;
};
class A : virtual public O{
public: void print(){
std::cout<<database<<std::endl;
}
};
class B : virtual public O{
public: void set(int s){
database=s+1;
}
};
class AB : protected A, protected B{}; // no vtable
void foo() {
AB ab;
ab.print(); // won't perform virtual call.
}
I'm reading the book by Alexandrescu, and I've run into the Acyclic Visitor pattern. I think that it's possible to get rid of the macross that calls AcceptImpl method of the BaseVisitable class.
Could you tell me, whether the following implementation bellow conforms the standard?
class BaseVisitor
{
public:
virtual ~BaseVisitor() {}
};
template <class SpecificVisitable>
class SpecificVisitor
{
public:
virtual void Visit(SpecificVisitable& t) = 0;
protected:
~SpecificVisitor() {}
};
template <class SpecificVisitable>
class BaseVisitable
{
public:
void Accept(BaseVisitor& visitor)
{
SpecificVisitor<SpecificVisitable>& specificVisitor = dynamic_cast<SpecificVisitor<SpecificVisitable>&>(visitor);
specificVisitor.Visit(static_cast<SpecificVisitable&>(*this));
}
protected:
~BaseVisitable() {}
};
class A : public BaseVisitable<A>
{
public:
void PrintA() { std::cout << "A\n"; }
};
class B : public BaseVisitable<B>
{
public:
void PrintB() { std::cout << "B\n"; }
};
class PrintVisitor final:
public BaseVisitor,
public SpecificVisitor<A>,
public SpecificVisitor<B>
{
public:
virtual void Visit(A& a) override
{
a.PrintA();
}
virtual void Visit(B& b) override
{
b.PrintB();
}
};
int main()
{
A a;
B b;
PrintVisitor visitor;
a.Accept(visitor);
b.Accept(visitor);
}
I agree with the commenters to the original post that state that a dynamic_cast to a reference will fail. You are not testing that situation, so your code will of course work just fine. But, in the general case, it's wrong.
I recommend that you instead rewrite BaseVisitable to instead cast to a pointer and check that pointer before dispatching on it. Something like
if (auto sv = dynamic_cast<SpecificVisitor<SpecificVisitable>*>(visitor))
sv->visit(*this)