inject implementation to a single multi-function interface class - many CRTP classes? - c++

How to create many classes to act like implementer for an interface class, while avoid v-table cost as possible, and still enable static casting to the interface?
For a simple case, it can be achieved like in the below example.
Example
Library Code :-
class I{ //interface
public: virtual void i1()=0;
};
template<class Derived>class Router : public I{
public: virtual void i1()final{
//in real case it is very complex, but in the core is calling :-
static_cast<Derived*>(this)->u1();
}
};
User Code :-
class User : public Router<User>{
public: void u1(){ std::cout<<"hi"<<std::endl; }
};
int main() {
User u;
u.i1(); //<-- no v-table cost
I* i=&u;
i->i1(); //<-- has v-table cost (OK)
}
Full demo
Question
How to extend the above feature to support 2 routes or more?
The below code is uncompilable, but it depicts my dream. (full demo).
Library Code :-
class I{ //interface
public: virtual void i1()=0;
public: virtual void i2()=0;
};
template<class Derived>class RouterI1U1 : public I{
public: virtual void i1()final{ static_cast<Derived*>(this)->u1(); }
};
template<class Derived>class RouterI1U2 : public I{
public: virtual void i1()final{ static_cast<Derived*>(this)->u2(); }
};
template<class Derived>class RouterI2U1 : public I{
public: virtual void i2()final{ static_cast<Derived*>(this)->u1(); }
};
template<class Derived>class RouterI2U2 : public I{
public: virtual void i2()final{ static_cast<Derived*>(this)->u2(); }
};
User Code :-
The one who want to use the above library, can easily pick whatever "route" he want.
derived from RouterI1U2<User> and RouterI2U1<User> or
derived from RouterI1U1<User> and RouterI2U2<User> or
derived from {RouterI1U1<User> or RouterI1U2<User>} and implement i2() with final manually or
derived from {RouterI2U2<User> or RouterI2U1<User>} and implement i1() with final manually or
implement i1() and i2() with final manually
Here is an dreamed example of usage.
class User : public RouterI1U2<User>,public RouterI2U1<User>{
public: void u1(){ std::cout<<"hi1"<<std::endl; }
public: void u2(){ std::cout<<"hi2"<<std::endl; }
};
int main() {
User u;
u.i1(); //<-- no v-table cost
I* i=&u;
i->i1(); //<-- has v-table cost (OK)
}
My poor solution
class I{ //interface
public: virtual void i1()=0;
public: virtual void i2()=0;
};
template<class Derived> class RouterI1U2_I2U1 : public I{ //group it
public: virtual void i1()final{ static_cast<Derived*>(this)->u2(); }
public: virtual void i2()final{ static_cast<Derived*>(this)->u1(); }
};
class User : public RouterI1U2_I2U1<User>{
public: void u1(){ std::cout<<"hi1"<<std::endl; }
public: void u2(){ std::cout<<"hi2"<<std::endl; }
};
It works (demo), but offer less modularity. (low re-usability)
I have to pack RouterI1U2 and RouterI2U1 to RouterI1U2_I2U1 manually.

It may not apply in your case, but could be useful to other reading the question as well.
I suggest you to use the concept-model idiom for this particular case. The goal of this is to separate the polymorphism implementation and the implementation of those class themselves into different part. Here, I becomes a polymorphic wrapper around any class that has i1 and i2 member functions:
class I {
// The interface is internal, invisible to outside
// We use this as a type erasure technique and polymorphism
struct Concept {
virtual void i1() = 0;
virtual void i2() = 0;
};
// The single implementation that directly
// extend the interface is the model. T is the user class.
// T must have i1 and i2 function, because we call them.
template<typename T>
struct Model : Concept {
// The user class.
// If you want, you can use a reference there if you
// need references semantics with I
T user;
Model (T u) : user{std::move(u)} {}
// The only implementation of i1 is to call i1 from the user class
void i1() override {
user.i1();
}
void i2() override {
user.i2();
}
};
// Or use a shared, or use SBO
std::unique_ptr<Concept> concept;
public:
// When we make an I, we must provide a user class.
// If the user class had i1 and i2, it will compile.
// If Model takes a reference, use a reference there too.
template<typename T>
I(T model) : concept{std::make_unique<Model<T>>(std::move(model))} {}
void i1() {
concept->i1();
}
void i2() {
concept->i2();
}
};
Then, your classes that provide implementations becomes like this:
template<class Derived>
struct RouterI1U1 { // no Inheritance needed
void i1() { static_cast<Derived*>(this)->u1(); }
};
template<class Derived>
struct RouterI1U2 {
void i1() { static_cast<Derived*>(this)->u2(); }
};
template<class Derived>
struct RouterI2U1 {
void i2() { static_cast<Derived*>(this)->u1(); }
};
template<class Derived>
struct RouterI2U2 {
void i2() { static_cast<Derived*>(this)->u2(); }
};
Since these i1 and i2 only needs to be "there" in order to fit into the Model<T> class, no overriding is needed, so no virtual inheritance.
It would effectively look like this when used:
struct User : RouterI2U2<User> {
void i1() {}
void u2() {}
};
As you can see, we don't have any virtual method. The polymorphism is an implementation detail of I. Since this class have all required member functions, the I class will allow it.
And using the class I too is quite simple. Let User2 be another user class that fits I requirements:
User2 user2;
user2.i1(); // no vtable, so no vtable overhead possible
I myI{user2}; // works!
myI.i2(); // calls u2, with vtable
std::vector<I> v;
v.emplace_back(User2{});
v.emplace_back(User{}); // simple heh?
Here's how you can remove the router classes, and implement this thing with an "or" style interface. I mean an interface that allows you to implement something or something else.
In the Model<T> class, you can check if i1 and i2 exists. If there are not existing, you can provide an implementation that calls u1 and u2 instead.
We start that by making type traits that can tell us if a particular type T has the member function i1 or i2:
template<typename...>
using void_t = void;
template<typename, typename>
struct has_i1 : std::false_type {};
template<typename T>
struct has_i1<T, void_t<decltype(std::declval<T>().i1())>> : std::true_type {};
template<typename, typename>
struct has_i2 : std::false_type {};
template<typename T>
struct has_i2<T, void_t<decltype(std::declval<T>().i2())>> : std::true_type {};
Now, we can change our model implementation to call u1 or u2 if i1 and i2 are not there:
template<typename T>
struct Model : Concept {
T user;
Model(T u) : user{std::move(u)} {}
void i1() override {
i1_helper(user);
}
void i2() override {
i2_helper(user);
}
private:
template<typename U>
auto i1_helper(U& u) -> std::enable_if_t<has_i1<U>::value> {
// Call i1 if has i1
u.i1();
}
template<typename U>
auto i1_helper(U& u) -> std::enable_if_t<!has_i1<U>::value> {
// Call u1 if has not i1
u.u1();
}
template<typename U>
auto i2_helper(U& u) -> std::enable_if_t<has_i2<U>::value> {
// Call i2 if has i2
u.i2();
}
template<typename U>
auto i2_helper(U& u) -> std::enable_if_t<!has_i2<U>::value> {
// Call u2 if has not i2
u.u2();
}
};
Now, your user classes are the simplest possible.
struct User1 {
void i1() {}
void i2() {}
};
struct User2 {
void i1() {}
void u2() {}
};
struct User3 {
void u1() {}
void i2() {}
};
struct User4 {
void u1() {}
void u2() {}
};

Use virtual inheritance.
template<class Derived>class RouterI1U1 : public virtual I{
etc. makes the code compilable.

Related

Is it possible to override functionality with a mixin-like pattern in c++

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.

How to implement a fully generic Visitor for a hierarchy of classes in C++1x?

I'd like to implement a fully generic Visitor pattern using >= C++14 using template metaprogramming. I've already found a nice way to generalize the Visitor itself, but I'm having trouble defining the Visitables. The code below works, but I'd like the commented out code in main to work as well; in particular, I want to be able to have a collection of Visitables and apply a Visitor to each element.
Is what I'm trying to do even possible in C++?
Things I've tried:
class X : public Visitable<X>
This solves the problem of not having a suitable accept method in
X, but results in ambiguities X/A and X/B which the compiler
cannot resolve.
empty accept method in X without inheriting; works, but the
specialized accept methods in A and B are never called.
replace template class Visitor with regular class with function
template visit for arbitrary types; does not really change the
semantics, but is less readable IMHO
#include <iostream>
#include <vector>
template <typename I>
class Visitable {
public:
template <typename Visitor>
void accept(Visitor&& v) const {
v.visit(static_cast<const I&>(*this));
}
};
template <typename T, typename... Ts>
class Visitor : public Visitor<Ts...> {
public:
virtual void visit(const T& t);
};
template<typename T>
class Visitor<T> {
public:
virtual void visit(const T& t);
};
struct X {
// template <typename V> void accept(V&& v) const {};
};
struct A : public X, public Visitable<A> {};
struct B : public X, public Visitable<B> {};
class MyVisitor : public Visitor<A, B> {
public:
void visit(const A& a) override { std::cout << "Visiting A" << std::endl; }
void visit(const B& b) override { std::cout << "Visiting B" << std::endl; }
};
int main() {
MyVisitor v {};
// std::vector<X> elems { A(), B() };
// for (const auto& x : elems) {
// x.accept(v);
// }
A().accept(v);
B().accept(v);
}
There are a few issues with your current solution:
You don't have a polymorphic type that can represent any visitable type. This means that you don't have a way to properly store all your A and B values in a collection such that you can visit every element in the collection. X doesn't accomplish this because there is no way to require that a subclass of X also subclasses an instantiation of the Visitable class template.
You have no way of handling a mismatch of visitor/visitable types; you cannot guarantee that all values in your collection are visitable by some visitor type, without simply making the collection a vector<A> or vector<B>, in which case you lose the ability to store values of different visitable types in the same collection. You either need a way to handle at runtime the scenario of a visitor/visitable mismatch, or you need a much more complex template structure.
You cannot store polymorphic values directly in a collection. This is because vector stores its elements consecutively in memory, and therefore must assume a certain constant size for each element; by their nature polymorphic values have an unknown size. The solution is to use a collection of (smart) pointers to refer to polymorphic values elsewhere on the heap.
Here's a working adaptation of your original code:
#include <iostream>
#include <vector>
#include <memory>
template<typename T>
class Visitor;
class VisitorBase {
public:
virtual ~VisitorBase() {}
};
class VisitableBase {
public:
virtual void accept(VisitorBase& v) const = 0;
virtual ~VisitableBase() {}
};
template <typename I>
class Visitable : public VisitableBase {
public:
virtual void accept(VisitorBase& v) const {
auto visitor = dynamic_cast<Visitor<I> *>(&v);
if (visitor == nullptr) {
// TODO: handle invalid visitor type here
} else {
visitor->visit(dynamic_cast<const I &>(*this));
}
}
};
template<typename T>
class Visitor : public virtual VisitorBase {
public:
virtual void visit(const T& t) = 0;
};
struct A : public Visitable<A> {};
struct B : public Visitable<B> {};
class MyVisitor : public Visitor<A>, public Visitor<B> {
public:
void visit(const A& a) override { std::cout << "Visiting A" << std::endl; }
void visit(const B& b) override { std::cout << "Visiting B" << std::endl; }
};
int main() {
MyVisitor v {};
std::vector<std::shared_ptr<VisitableBase>> elems {
std::dynamic_pointer_cast<VisitableBase>(std::make_shared<A>()),
std::dynamic_pointer_cast<VisitableBase>(std::make_shared<B>())
};
for (const auto& x : elems) {
x->accept(v);
}
A().accept(v);
B().accept(v);
}
struct empty_t{};
template <class I, class B=empty_t>
class Visitable:public B {
public:
// ...
struct X : Visitable<X>{
};
struct A : Visitable<A,X> {};
struct B : Visitable<B,X> {};
Note however that dispatch here is static. And your vector contains Xs not As or Bs.
You probably want
template <class Visitor>
struct IVisitable {
virtual void accept(Visitor const& v) const = 0;
protected:
~IVisitable(){}
};
template <class I, class Visitor, class B=IVisitable<Visitor>>
struct Visitable {
virtual void accept(Visitor const& v) const override {
v.visit(static_cast<const I&>(*this));
}
};
which gets closer.
struct A; struct B; struct X;
struct X:Visitable<X, Visitor<A,B,X>> {
};
struct A :Visitable<A, Visitor<A,B,X>, X> {};
struct B :Visitable<B, Visitor<A,B,X>, X> {};
this still doesn't do what you want, because you have a vector of values. And polymorphic values require more work.
Make it a vector of unique ptrs to X, and add virtual ~X(){} and some * and make_uniques and this will do what you want.

Diamond inheritance - call all parent functions

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

Choosing which base class to override method of

Given the following:
class Observer
{
public:
virtual void Observe(Parameter p) = 0;
};
template<size_t Tag>
class TaggedObserver : public Observer { };
class Thing : public TaggedObserver<0>, TaggedObserver<1>
{
public:
virtual void Observe(Parameter p) override;
};
Thing::Observe overrides both TaggedObserver<0>::Observe and TaggedObserver<1>::Observe.
Is there a way to provide a different override for each base class?
Rationale: I want the class to be able to observe two notification sources of the same type with different actions for each source without having to resort to pass the source in the parameter and then checking it in an if/switch.
In order to provide different overrides, you need to define different derived classes, eg:
class Observer
{
public:
virtual void Observe(Parameter p) = 0;
};
template<size_t Tag>
class TaggedObserver : public Observer
{
};
class TaggedObserverZero : public TaggedObserver<0>
{
public:
virtual void Observe(Parameter p)
{
// do something ...
}
};
class TaggedObserverOne : public TaggedObserver<1>
{
public:
virtual void Observe(Parameter p)
{
// do something else ...
}
};
However, if you want Thing::Observe() to receive the Parameter first and dispatch it to the appropriate base class, you can't avoid using an if statement (or equivalent) in Thing, since it inherits multiple copies of TaggedObserver::Observe() and needs to decide which one to call:
class Thing : public Observer, TaggedObserverZero, TaggedObserverOne
{
public:
virtual void Observe(Parameter p)
{
if (some condition)
TaggedObserverZero::Observe(p);
else if (some other condition)
TaggedObserverOne::Observe(p);
}
};
Or, you call just them both unconditionally and let them figure out what to do:
class TaggedObserverZero : public TaggedObserver<0>
{
public:
virtual void Observe(Parameter p)
{
if (some condition)
// do something ...
}
};
class TaggedObserverOne : public TaggedObserver<1>
{
public:
virtual void Observe(Parameter p)
{
if (some other condition)
// do something else ...
}
};
class Thing : public Observer, TaggedObserverZero, TaggedObserverOne
{
public:
virtual void Observe(Parameter p)
{
TaggedObserverZero::Observe(p);
TaggedObserverOne::Observe(p);
}
};
Implement them in TaggedObserver (provide explicit specialization if needed), as an example:
class Observer {
public:
virtual void Observe(Parameter p) = 0;
};
template<size_t Tag>
class TaggedObserver : public Observer {
public:
void Observe(Parameter p) override { }
};
template<std::size_t... I>
class Thing : public TaggedObserver<I>... {
public:
Thing(): TaggedObserver<I>{}... {}
template<std::size_t N>
void Observe(Parameter p) {
TaggedObserver<N>::Observe(p);
}
};
Then, you can specialize Thing as Thing<0, 1> and invoke the right function using thing.Observe<1>(p).
EDIT
The purpose of this edit is to show a new example code, that is more or less the one above even if slightly modified.
I hope this can help the OP. The basic idea is to combine CRTP idiom, virtual methods and inheritance.
class Observer {
public:
virtual void Observe(Parameter p) = 0;
};
template<template T, size_t Tag>
class TaggedObserver : public Observer {
public:
void Observe(Parameter p) override {
T *t = static_cast<T*>(this);
// Now use whatever you want from T, that is Thing in this example
}
};
template<std::size_t... I>
class Thing : public TaggedObserver<Thing<I...>, I>... {
template<std::size_t J>
friend class TaggedObserver<Thing<I...>, J>;
public:
Thing(): TaggedObserver<Thing<I...>, I>{}... {}
template<std::size_t N>
void Observe(Parameter p) {
TaggedObserver<Thing<I...>, N>::Observe(p);
}
};
Note that the friend declaration allows TaggedObservers to access private members of Thing.
This way, implementations of Observe in TaggedObservers can access public, protected and private members from Thing, as requested in the comments.
Finally you can specialize TaggedObserver if needed, so as to provide different implementations for Observe.
As an example:
template<template T, size_t Tag>
class TaggedObserver;
template<template T>
class TaggedObserver<T, 0>: public Observer {
public:
void Observe(Parameter p) override {
T *t = static_cast<T*>(this);
// Now use whatever you want from T, that is Thing in this example
// Put here the code of the specialization for Tag 0
}
};
template<template T>
class TaggedObserver<T, 1>: public Observer {
public:
void Observe(Parameter p) override {
T *t = static_cast<T*>(this);
// Now use whatever you want from T, that is Thing in this example
// Put here the code of the specialization for Tag 1
}
};

Template a virtual method from base class instead of use overloading

I got strange code and have to extend it. But instead of copy paste many many times i decided to create a template. But get caught by a terrible rock.
Here is an example code:
template<typename T>
class anyClass {};
template<typename T>
class Outer : public anyClass<T>
{
public:
using value_t = T;
class Inner
{
virtual void foo(value_t);
};
};
class specializer : protected Outer::Inner
{
virtual void foo(int) override {}
}
I have to extend virtual void foo(value_t) in specializer.
Example:
class specializer : protected Outer::Inner
{
virtual void foo(int) override {}
virtual void foo(float) override {}
virtual void foo(string) override {}
virtual void foo(bar) override {}
// And so on...
}
Question 1: Why works the example, although class specializer : protected Outer::Inner miss a param?
All overloadings do nearly the same. I created already the function.
template<typename anyType>
void meow( anyType )
{
/***/
}
My problem is here:
virtual void foo(anytype value) //<< replace anytype with what?
{
meow<anytype>( value );
}
I need the type Outer::value_T but i don't know how to get it.
Question 2: How can i use meow by calling foo ?
Feel free to ask for more information.
UPDATE
I looked again in the origin code and realised, that i've overlooked an important using/typedef.
The working code looks like:
class specializer : protected Outer<int, float, string, bar>::Inner //Yes a variadic-template
{
virtual void foo(int) override {}
virtual void foo(float) override {}
virtual void foo(string) override {}
virtual void foo(bar) override {}
// And so on...
}
So Question 1 is solved.
Why works the example, although class specializer : protected Outer::Inner miss a param?
The example does not work. It does not work because Outer is not a type. Also, you override multiple overloads of foo even though inner has only one foo. There are several syntax errors too. If it appears to work, then the compiler is doing something non-standard.
About your second question:
virtual void foo(anytype value) //<< replace anytype with what?
You replace it with the type whose overload you intend to override. For example, if you intend to override foo(int), then replace anytype with int.
Question 2: How can i use meow by calling foo ?
Simply call meow in foo.
You would have to make specializer a template class.
#include <iostream>
template<typename T> void meow(T x)
{
std::cout << x << std::endl;
}
template<typename T>
class anyClass {};
template<typename T>
class Outer : public anyClass<T>
{
public:
using value_t = T;
class Inner
{
virtual void foo(Outer<T>::value_t);
};
};
template<typename T>
class specializer : protected Outer<T>::Inner
{
virtual void foo(T x) override
{
meow(x);
}
};
I wonder how this would help you to change the behavior in Outer or anyClass because you have not shown code which shows where and how Inner is actually used. Without that, it's just guessing.
I have the feeling that what you are actually trying to achieve is to pass a function (or Strategy?) to you Outer class, represented by Inner in your code. That would be better done by passing it as a template argument.
template<typename T>
class anyClass {};
template<typename T, typename Inner = meow<T>>
class Outer : public anyClass<T>
{
public:
using value_t = T;
// somewhere in your code
Inner i;
i.meow( any_value );
};
You can also pass a std::function to the constructor.
template
class anyClass {};
template<typename T>
class Outer : public anyClass<T>
{
public:
using value_t = T;
Outer( std::function<void (value_t)> inner);
// somewhere in your code
i.meow( any_value );
std::function<void (value_t)> i;
};
Originally I simplyfied a little bit to much.
Here is the compileable example of my problem: http://ideone.com/9U7J1a
I removed all unconducive code. I know the design is horrible but i have no influence on it.
class bar {};
class string {};
template<typename _T>
class ModelContainer
{
public:
using value_type = _T;
class Delegate {
public:
virtual void foo( value_type value);
};
};
template< typename... _Ts >
class ModelManager__AbstractBase : protected ModelContainer< _Ts >...
{
public:
class Delegate : public ModelContainer< _Ts >::Delegate... {
public:
virtual ~Delegate( ) = default;
};
};
using ModelManager__Base = ModelManager__AbstractBase<
int,
float,
string,
bar
>;
class ModelManager : public ModelManager__Base {
/* Some functions */
};
class spezializer : ModelManager::Delegate
{
public:
virtual ~spezializer() = default;
//Uncommend to see my error
// virtual void foo( value_type value) override // << value_type unknown
// {/* Calling everytime the same method, no matter which value_type*/}
};