I have a class defined as follows:
template< typename... >
class Base;
template< typename T >
class Base<T>{
//pure virtual functions dependent on T
public:
virtual ~Base() = default;
};
template< typename... Ts >
class Base<Ts...>
: public Base<Ts>...
{
//empty
};
The questions are:
Is there a way to cast Base< T1, T2, T3 >& to Base< T2, T3 >&?
Is there a way to cast Base< T1, T2, T3 >& to Base< T2, T1, T3 >&?
EDIT:
Let me rephrase the question without the templates.
I have a class defined as follows:
class Base_int{
public:
virtual int f() = 0;
virtual ~Base_int() = default;
};
class Base_float{
public:
virtual float f() = 0;
virtual ~Base_float() = default;
};
class Base_double{
public:
virtual double f() = 0;
virtual ~Base_double() = default;
};
class IFD
: public Base_int
, public Base_float
, public Base_double
{ };
class IF
: public Base_int
, public Base_float
{ };
class FID
: public Base_float
, public Base_int
, public Base_double
{ };
The questions are:
Is there a way to cast IFD& to IF&?
Is there a way to cast IFD& to FID&?
EDIT 2:
To further clarify:
I'm impementing a generic visitor pattern implementation which I will be using in a generic tree container. I'm using the mixin (CRTP) pattern to implement accept method of visited classes as well as visit method of visitors. These methods are virtual and I need the hierarchy I posted in the OP.
There is a base class called IVisitor<Ts...> that implements an interface of the visitor that visits Ts.... This interface is composed of classes IVisitor<T> - just as in the OP.
A concrete visitor that implements the IVisitor<Ts...> is defined as follows:
class ConcreteVisitor : public IVisitor<T1, T2, T2, ...>{
//Implementation of the visit methods defined in IVisitor<Ts...>
virtual void visit( T1& v ) override { /*...*/ }
virtual void visit( T2& v ) override { /*...*/ }
virtual void visit( T3& v ) override { /*...*/ }
}
It occurred to me that it would be useful if the ConcreteVisitor could visit stuff in the IVisitor<Us...> where Us... is a subset, or a permutation of Ts.... In order to do that, I need to cast it to that base - hence the question.
After examining the problem some more I realized that what I needed a wrapper that adapts generic visitors to my interfaces. This is the solution I went with - see the IVisitable::adaptVisitor static method:
#include <iostream>
#include <typeinfo>
#include <vector>
//Visitable base class
template< typename >
class Visitable;
//Visitable class interface
template< typename... >
class IVisitor;
//Assures that the visitor type derives from IVisitor
template< typename IVisitor_type >
class IVisitable
: public IVisitable<typename IVisitor_type::derives_from_IVisitor>
{ };
//Implements the Visitor adapter
template< typename Derived, typename Root, typename... Ts >
class VisitorWrapper;
//IVisitable base class
template< typename... Ts >
class IVisitable< IVisitor<Ts...> >{
public:
//Visitor interface type
using IVisitor = IVisitor<Ts...>;
//Visitor adapter type
template< typename F >
class VisitorAdapter;
//Helper function
template< typename F >
static VisitorAdapter<F&&> adaptVisitor( F&& f )
{ return { std::forward<F>(f) }; }
//Accept visitor pure virtual methods
virtual void accept( IVisitor& ) = 0;
virtual void accept( IVisitor& ) const = 0;
virtual void accept( IVisitor&& ) = 0;
virtual void accept( IVisitor&& ) const = 0;
protected:
virtual ~IVisitable() = default;
};
//Implements the visitor adapter of F class
template< typename... Ts >
template< typename F >
class IVisitable<IVisitor<Ts...>>::VisitorAdapter
: public VisitorWrapper< VisitorAdapter<F>, ::IVisitor<Ts...>, Ts... >
//Derives from VisitorWrapper that implements all of the virtual methods
{
public:
template< typename U >
void visit( U&& u ){ f( std::forward<U>(u) ); }
VisitorAdapter( F f_ ) : f(f_) { }
F f;
};
//Basic IVisitor of T
template< typename T >
class IVisitor<T>{
public:
using derives_from_IVisitor = IVisitor;
virtual void visit( T& ) = 0;
virtual void visit( const T& ) = 0;
virtual ~IVisitor() = default;
};
//IVisitor of Ts derives from Visitor<T>
template< typename T, typename... Ts >
struct IVisitor<T, Ts...>
: IVisitor<T>, IVisitor<Ts...>
{
using derives_from_IVisitor = IVisitor;
};
//Visitable base class. Final to prevent errors
template< typename Derived >
struct Visitable final
{
//Extends class wraps the Base class inheritance
template< typename Base >
class extends : public Base
{
public:
//Propagate the IVisitor interface.
using IVisitor = typename Base::IVisitor;
//Prevents incomprehensible errors when visitor doesn't
//define Derived as its visited class
static_assert(
std::is_base_of<::IVisitor<Derived>, IVisitor>::value
, "Base class visitor interface does not support visitation of this type"
);
//Implement accept method via CRTP
virtual void accept( IVisitor& v ) override{
static_cast< ::IVisitor<Derived>& >(v).visit( // Disambiguation
static_cast<Derived&>(*this) // CRTP
);
}
virtual void accept( IVisitor& v ) const override {
static_cast< ::IVisitor<Derived>& >(v).visit( // Disambiguation
static_cast<const Derived&>(*this) // CRTP
);
}
virtual void accept( IVisitor&& v ) override{
static_cast< ::IVisitor<Derived>&& >(v).visit( // Disambiguation
static_cast<Derived&>(*this) // CRTP
);
}
virtual void accept( IVisitor&& v ) const override{
static_cast< ::IVisitor<Derived>&& >(v).visit( // Disambiguation
static_cast<const Derived&>(*this) // CRTP
);
}
protected:
virtual ~extends() = default;
};
~Visitable() = delete;
};
template< typename > struct print_type;
//Uses CRTP to implement visit method of IVisitor
//Consumes the list of Ts... so that the inheritance hierarchy is linear
template<
typename Derived // CRTP
, typename... Rs // Base class (IVisitor<Rs...>)
, typename T // Currently implemented type
, typename... Ts // The rest of types
> class VisitorWrapper< Derived, IVisitor<Rs...>, T, Ts... >
: public VisitorWrapper< Derived, IVisitor<Rs...>, Ts... > //Consume T
{
//Cast to Derived and call visit method
virtual void visit( T& v ){ static_cast<Derived*>(this)->visit(v); }
virtual void visit( const T& v ){ static_cast<Derived*>(this)->visit(v); }
};
//Uses CRTP to implement visit method of IVisitor
template< typename Derived, typename... Rs, typename T >
class VisitorWrapper< Derived, IVisitor<Rs...>, T >
: public IVisitor<Rs...> //IVisitor<Ts...>
{
virtual void visit( T& v ){ static_cast<Derived*>(this)->visit(v); }
virtual void visit( const T& v ){ static_cast<Derived*>(this)->visit(v); }
};
/////////////////////////////////////////////////////
class ABCVisitor
: public IVisitor< class A, class B, class C >
{ };
class ABC : public IVisitable< ABCVisitor >
{};
class A : public Visitable<A>::extends<ABC> {};
class B : public Visitable<B>::extends<ABC> {};
class C : public Visitable<C>::extends<B> {};
int main()
{
auto p = [](const auto& v){ std::cout << typeid(v).name() << std::endl; };
auto printer = ABC::adaptVisitor( p );
A a; B b; C c;
std::vector< ABC* > vs{ &a, &b, &c };
for( const auto& v : vs )
v->accept(printer);
return 0;
}
I am not really sure if this is what you are looking for, but here it goes.
I would make the accept method of the base classes templated so that they can accept any visitor as long as the visitor has the right concept. In particular:
#include <iostream>
template <class Derived>
struct Base {
// templated visitor so that it can take any argument as long as it has the right concept
template <class Visitor>
void accept(Visitor& visitor) {
visitor.visit(static_cast<Derived&>(*this));
}
};
struct T1
: Base<T1> {};
struct T2
: Base<T2> {};
struct T3
: Base<T3> {};
struct Visitor1 {
void visit(T1& t1) {
std::cout << "Visiting T1 from Visitor1" << std::endl;
}
void visit(T2& t2) {
std::cout << "Visiting T2 from Visitor1" << std::endl;
}
};
struct Visitor2 {
void visit(T1& t1) {
std::cout << "Visiting T1 from Visitor2" << std::endl;
}
void visit(T2& t2) {
std::cout << "Visiting T2 from Visitor2" << std::endl;
}
void visit(T3& t3) {
std::cout << "Visiting T3 from Visitor2" << std::endl;
}
};
int main(int argc, const char * argv[]) {
Visitor1 visitor1;
Visitor2 visitor2;
T1 t1;
T2 t2;
T3 t3;
t1.accept(visitor1);
t1.accept(visitor2);
t2.accept(visitor1);
t2.accept(visitor2);
t3.accept(visitor2);
// t3.accept(visitor1); // triggers a compilation error as visitor1 cannot handle T3 types
}
This way you no longer have to do any casts of your visitor classes.
I don't think you need to cast to visitor with permuted parameters to accomplish what you want, the only thing you need is additional level of abstraction - variadic template wrapper to your visitor. Find the code below:
struct VisitorParent {
virtual ~VisitorParent() = default;
};
template <class T>
struct VisitorImpl: virtual VisitorParent {
virtual void visit(T &t) {
//...
}
};
template <class... Ts>
struct Visitor: virtual VisitorImpl<Ts>... { };
template <class T>
struct VisitorWrapperImpl {
VisitorParent *vp;
VisitorWrapperImpl(VisitorParent *vp): vp(vp) {}
void visit(T &t) {
VisitorImpl<T> *cvi = dynamic_cast<VisitorImpl<T> *>(vp);
if (cvi) {
cvi->visit(t);
}
}
};
template <class... Ts>
struct VisitorWrapper: VisitorWrapperImpl<Ts>... {
VisitorWrapper(VisitorParent *vp): VisitorWrapperImpl<Ts>(vp)... { }
template <class T>
void visit(T &t) {
VisitorWrapperImpl<T>::visit(t);
}
};
int main() {
Visitor<int, char, float> v;
VisitorWrapper<char,float> vw(&v);
char c;
vw.visit(c);
}
Another idea would be to have the accept method taking one of the base classes of the visitor. This way you can pass any visitor to the accept method since all visitors can be casted to the single base visitor class. I believe this will work for you:
#include <iostream>
// one of the base classes of your concrete visitors
template <class T>
struct VisitorUnit {
virtual void visit(T& t) = 0;
};
// the visitor interface which will be implemented by concrete visitors
template <class... T>
struct Visitor
: VisitorUnit<T>... {
};
// the base class of your leaf classes
template <class Derived>
struct Base {
void accept(VisitorUnit<Derived>& visitor) {
visitor.visit(static_cast<Derived&>(*this));
}
};
struct T1: Base<T1>{};
struct T2: Base<T2>{};
struct T3: Base<T3>{};
struct Visitor1
: Visitor<T1, T2, T3> {
void visit(T1& t) override {
std::cout << "T1 from Visitor1" << std::endl;
}
void visit(T2& t) override {
std::cout << "T2 from Visitor1" << std::endl;
}
void visit(T3& t) override {
std::cout << "T3 from Visitor1" << std::endl;
}
};
struct Visitor2
: Visitor<T3, T2> {
void visit(T2& t) override {
std::cout << "T2 from Visitor2" << std::endl;
}
void visit(T3& t) override {
std::cout << "T3 from Visitor2" << std::endl;
}
};
int main(int argc, const char * argv[]) {
T1 t1;
T2 t2;
T3 t3;
Visitor1 visitor1;
Visitor2 visitor2;
visitor1.visit(t1);
visitor1.visit(t2);
visitor1.visit(t3);
visitor2.visit(t2);
visitor2.visit(t3);
}
Related
Suppose to have the following class structure:
template <typename T, typename U>
class Base
{
public:
virtual ~Base<T, U>(){};
virtual U show() = 0;
protected:
T foo;
};
class DerivateA : public Base<int, int>
{
public:
DerivateA() { foo = 7; };
virtual int show() override { return foo; };
};
class DerivateB : public Base<std::string, std::string>
{
public:
DerivateB() { foo = "Hello"; };
virtual std::string show() override { return foo; };
};
Is there any way I can create a factory object with a Create() function that, based on an input value, returns a pointer to either DerivateA or DerivateB?
Not sure if I understood your issue correctly, but it could be smth like:
template<typename T, typename U>
class Base
{
protected:
explicit Base(T arg) : foo{std::move(arg)} {}
public:
virtual ~Base<T, U>() = default;
virtual U show() = 0;
protected:
T foo;
};
template<typename T>
class Derivate : public Base<T, T>
{
using base_type = Base<T, T>;
public:
explicit Derivate(const T& arg) : base_type(arg) { };
T show() override { return base_type::foo; };
};
class Factory
{
public:
template<typename T>
static Derivate<T>* create(const T& arg)
{ return new Derivate<T>{arg}; }
};
and we could use it like:
Base<int, int>* d1 = Factory::create(3);
Base<string, string>* d2 = Factory::create(string{"string"});
Suppose there are classes:
struct A {
int a;
virtual size_t GetMemoryUsage() const {
return sizeof(*this);
}
};
struct B : public A {
int b;
};
And there may be deeper inheritance.
What I want is to have a method which will return the number of bytes an object occupies in memory, GetMemoryUsage() in this case. Usually it can be achieved by using sizeof(*this). The problem is (at least AFAIU) that I have to override the method in each derived class and actually copy-paste its body. I don't like duplicated code :)
Am I correct? How can I make sizeof(*this) and decltype(*this) return what I want in subclasses, by calling them only from base class's methods? Is there a more elegant solution?
You do not have to implement GetMemoryUsage for each of your derived classes manually, just leave it as pure virtual. E.g.:
struct A
{
virtual ~A() = default;
virtual size_t GetMemoryUsage() const noexcept = 0;
};
struct B : A
{
int b;
};
When creating objects, however, that function must be implemented. You can do that using a factory function that "decorates" the class with a generic implementation of that pure virtual:
// Can alternatively be defined inside function template create.
template<class T>
struct GetMemoryUsageImpl : T
{
using T::T;
size_t GetMemoryUsage() const noexcept final {
return sizeof(T);
}
};
template<class T, class... Args>
std::unique_ptr<T> create(Args&&... args) {
return std::unique_ptr<T>(new GetMemoryUsageImpl<T>(std::forward<Args>(args)...));
}
Usage:
void f(A& a) {
auto object_size = a.GetMemoryUsage();
}
int main() {
auto b = create<B>();
f(*b);
}
You can also implement a hierarchy of interfaces incrementally easily using this idiom.
This is an insanely generic version of #Maxim's solution.
template<class B0, template<class...>class... Z>
struct TemplateFold {
using type=B0;
};
template<class B0, template<class...>class... Z>
using TemplateFold_t = typename TemplateFold<B0, Z...>::type;
template<class B0, template<class...>class Z0, template<class...>class... Z>
struct TemplateFold<B0, Z0, Z...>
{
using type=Z0< TemplateFold_t<B0, Z...> >;
};
struct ExposeTrivial {
protected:
~ExposeTrivial() {}
};
template<class D, class B0=ExposeTrivial, class...Bases>
struct Expose:B0, Bases... {
// is a template because D isn't a real type when this class is instantiated:
template<class T>
using MakeConcreteType = TemplateFold_t< T, std::conditional_t< std::is_same<B0,ExposeTrivial>{}, T, B0 >::template Implement, Bases::template Implement... >;
template<class...Args>
static std::unique_ptr<D> create( Args&&... args ) {
using ConcreteType = MakeConcreteType<D>;
return std::unique_ptr<D>( new ConcreteType( std::forward<Args>(args)... ) );
}
protected:
~Expose() {}
};
// expose one thing:
struct ExposeMemoryUsage:Expose<ExposeMemoryUsage> {
virtual std::size_t GetMemoryUsage() const noexcept = 0;
template<class B>
struct Implement:B {
using B::B;
std::size_t GetMemoryUsage() const noexcept override final {
return sizeof(*this);
}
};
protected:
~ExposeMemoryUsage() {}
};
// expose a different thing:
struct ExposeAlignment:Expose<ExposeAlignment>{
virtual std::size_t GetAlignment() const noexcept = 0;
template<class B>
struct Implement:B {
using B::B;
std::size_t GetAlignment() const noexcept final override {
return alignof(decltype(*this));
}
};
};
// Expose two things:
struct Bob : Expose<Bob, ExposeMemoryUsage, ExposeAlignment> {
int x;
Bob( int v ): x(v) {}
virtual ~Bob() {}
};
int main() {
std::unique_ptr<Bob> ptr = Bob::create(7);
std::cout << ptr->x << " size:" << ptr->GetMemoryUsage() << " align:" << ptr->GetAlignment() << "\n";
// Bob b; // does not compile
}
simply add more "knows the derived type" static helpers in Exposer to increase functionality.
Live example.
How to use:
Create a Expose type. It should have a pure virtual member, and a template Implement class that (given a class that derives from the Expose type) implements that pure virtual member.
It should inherit from Expose<OwnType> (CRTP) to write the static ::create method for you.
If you want to inherit from additional Expose types (ie, compose two independent Expose interfaces that need to know the concrete type), instead inherit from Expose< YourType, OtherExposeType, AnotherExposeType >. Don't independently inherit from OtherExposeType or AnotherExposeType.
If you do this your Implement template won't be picked up.
I could improve this so that we detect Implement templates in both you and your bases, but that is more metaprogramming than I'm up for right now.
I want to get pointer to base class from boost variant, if I put orignally pointer to derived class. Is there some way to achive this . The following code does not work.
class A{ public: virtual ~A(){}}; class B : public A{};
typedef boost::variant<A*,B*> MyVar;
MyVar var = new B;
A* a = boost::get<A*> (var); // the following line throws exception
Maybe someone have idea how to write my own get function which will test if the requested type is base class of the stored type of in the variant,and then do the appropriate cast
You can write your own visitor with templated operator() like below:
LIVE DEMO
#include <iostream>
#include <boost/variant.hpp>
#include <type_traits>
struct A { virtual ~A() {} virtual void foo() {} };
struct B : A { virtual void foo() { std::cout << "B::foo()" << std::endl; } };
template <typename T>
struct visitor : boost::static_visitor<T>
{
private:
using Base = typename std::remove_pointer<
typename std::remove_cv<
typename std::remove_reference<T>::type
>::type
>::type;
template <typename U>
T get(U& u, std::true_type) const
{
return u;
}
template <typename U>
T get(U& u, std::false_type) const
{
throw boost::bad_get{};
}
public:
template <typename U>
T operator()(U& u) const
{
using Derived = typename std::remove_pointer<
typename std::remove_cv<
typename std::remove_reference<U>::type
>::type
>::type;
using tag = std::integral_constant<bool
, (std::is_base_of<Base, Derived>::value
|| std::is_same<Base, Derived>::value)
&& std::is_convertible<U, T>::value>;
return get(u, tag{});
}
};
template <typename T, typename... Args>
T my_get(boost::variant<Args...>& var)
{
return boost::apply_visitor(visitor<T>{}, var);
}
int main()
{
boost::variant<A*,B*> var = new B;
A* a = my_get<A*>(var); // works!
a->foo();
B* b = my_get<B*>(var); // works!
b->foo();
}
Output:
B::foo()
B::foo()
Q & A section:
This solution is weird!
No, it is not. This is exactly what the visitor classes in Boost.Variant are for. Similar solution already exists in latest release of Boost.Variant, which is boost::polymorphic_get<T>. Sadly it was designed for other purposes and cannot be used here.
Hi thank you all for your answers and comments
I came to the following which decides at compile time if types are inherited from each other. And it seems to work, and it seems much easier to me to understand.
#include <iostream>
#include <boost/variant.hpp>
#include <boost/type_traits.hpp>
#include <boost/utility.hpp>
using namespace boost::type_traits;
struct A { virtual ~A() {} virtual void foo() {} };
struct B : A { virtual void foo() { std::cout << "B::foo()" << std::endl; } };
typedef boost::variant<B*,A*,C*> MyVar;
template <typename A,typename B>
struct types_are_inheritance_related
{
static const bool value=
ice_or<
boost::is_base_of<A, B>::value,
boost::is_base_of<B, A>::value
>::value;
};
template<class Base>
class get_visitor
: public boost::static_visitor<Base*> { public:
template<class T>
Base* operator()( T* t, typename boost::enable_if<types_are_inheritance_related<Base,T> >::type* dummy = 0)
{
Base* b = dynamic_cast<Base*> ( t);
return b;
}
template<class T>
Base* operator()( T* t, typename boost::disable_if<types_are_inheritance_related<Base,T> >::type* dummy = 0)
{
return 0;
}
};
template<class T>
T* get_var_value(MyVar& var)
{
get_visitor<T> visitor;
T* aa= var.apply_visitor(visitor);
return aa;
}
int main()
{
MyVar var = new B;
A* a = get_var_value<A*>(var); // works!
a->foo();
B* b = get_var_value<B*>(var); // works!
b->foo();
}
I have a Base-class and a derived class. I would like to design a Class C that reacts differently when a base or derived object is handed over like this:
template<typename T>
class Base {};
class Derived: public Base<int>{}
template<typename T>
class C
{
public:
static int f(T&& arg) {return 1;};
};
// Specialize C, not the function
template<typename T>
class C<T>
{
public:
static int f(T&& arg) {return 2;};
};
template<typename T>
int function(T&& arg) {
return C<T>::f(std::forward<T>(arg));
}
int main()
{
std::cout << function(1) << std::endl;
std::cout << function(Base<float>()) << std::endl;
std::cout << function(Derived()) << std::endl;
}
This is supposed to print:
1
2
2
Is there a way that I can do this with specializing the class C and not the function. In reality I just hand over the type C and everything happens out of my reach.
To clearify, the implementation of function may look like that but I can't really tell. All I know is the signature of f: int f(T&&); And that I have to have a class C that has a function of that signature.
Through Specialization of function():
Example code first:
template< class T >
struct Base
{};
struct Child : Base<int>
{ };
template<typename T>
class C1
{
public:
static int f(T&& arg) {return 1;}
};
template<typename T>
class C2
{
public:
static int f(T&& arg) {return 2;}
};
template<typename T>
typename std::enable_if< std::is_base_of<Base<int>, T>::value, int >::type function(T&& arg)
{
return C2<T>::f(std::forward<T>(arg));
}
template<typename T>
typename std::enable_if< !std::is_base_of<Base<int>, T >::value, int >::type function(T&& arg)
{
return C1<T>::f(std::forward<T>(arg));
}
int main()
{
std::cout << function(1) << std::endl;
std::cout << function(Base<int>()) << std::endl;
std::cout << function(Child()) << std::endl;
return 0;
}
Why:
So the split here is that I've written two versions of function(). The return type of function() looks a little hairy but the first version will be compiled if T has Base< int > as a base type. Otherwise the second version will be used.
std::enable_if<> is a neat tool which causes the template expansion to fail if its condition is not met. In this case we cause the template expansion to fail if T does not have Base< int > as a base class. In the case that the template expansion fails the compiler continues to look for another version of function() which will compile.
C1 and C2 are then two different objects with C2 being used if T has Base as a child, otherwise C1 is used.
Through Specialization of C:
template< class BaseArgument >
Base< BaseArgument > get_Base_type_of( Base< BaseArgument >&& );
template< class T >
struct has_Base
{
typedef char yes;
typedef long no;
template< typename T1 >
static yes Check( decltype( get_Base_type_of( declval<T1>() ) )* );
template< typename T1 >
static no Check( ... );
static const bool value = sizeof( decltype( Check<T>(0) ) ) == sizeof( yes ) ;
};
template< typename T, typename Placeholder = void >
class C
{
public:
static int f(T&& arg) {return 1;};
};
template<typename T>
class C< T, typename std::enable_if< has_Base<T>::value >::type >
{
public:
static int f(T&& arg) {return 2;};
};
Pretty complicated (and bad) title, here's what I mean by example:
struct type1 {};
struct type2 {};
struct type3 {};
template< typename TYPE >
struct interface {
virtual void f( TYPE ) = 0;
};
struct processor {
template< typename TYPE >
void f( TYPE ) {
// something + for some TYPE-s have specializations, but it's irrelevant
}
};
struct der: interface< type1 >, interface< type2 >, interface< type3 > {
processor p;
void f( type1 t ){ p.f( t ); }
void f( type2 t ){ p.f( t ); }
void f( type3 t ){ p.f( t ); }
};
Is there any tricky way to avoid all overrides in der? In the real case, der inherits interface 10 times (with different template types and it could be extended in the future). And it's rather ugly to have 10+ overrides of f when their bodies are the same.
processor could be changed to anything, also der::p could be some container, holding a template-d processor, etc.
It sounds like I want to have a virtual template member function f, which is not allowed.
I thought about using a macro, but I don't like that idea.
EDIT Note: can't use c++11, unfortunately. And can't change typeN types, which are not in hierarchy.
C++03 solutions
(See KerrekSB's answer for solutions using C++11 features)
You can use another layer of inheritance and CRTP to dispatch the calls to your processor:
template< typename TYPE, class ProcessorHolder >
struct processorDispatch : interface<TYPE> {
virtual void f( TYPE t ) override {
processor& p = static_cast<ProcessorHolder*>(this)->p; //CRTP --> explicit downcast
p.f(t);
}
};
And use it as
struct der: processorDispatch< type1,der >, processorDispatch< type2,der >, processorDispatch< type3,der > {
processor p;
//make f visible - either
using processorDispatch< type1,der >::f;
using processorDispatch< type2,der >::f;
using processorDispatch< type3,der >::f;
//or
template <typename TYPE>
void f(TYPE t) {
processorDispatch<TYPE, der>::f(t);
}
}
};
A take at Kerrek's non-CRTP-solution, but "C++11-free" vía base class chaining:
struct der_base {
processor p;
};
template <class TYPE, class Base = der_base>
struct der_t : Base, interface<TYPE> {
void f(TYPE t) { this->p.f(t); }
using Base::f;
};
template <class TYPE>
struct der_t<TYPE, der_base> : der_base, interface<TYPE> {
void f(TYPE t) { this->p.f(t); }
};
And then use
typedef der_t<type1, der_t<type2, der_t<type3> > > der;
You could make der a template:
template <typename ...> struct der;
template <> struct der<>
{
processor p;
};
template <typename Base, typename ...Rest>
struct der<Base, Rest...> : der<Rest...>, interface<Base>
{
void f(Base x) { this->p.f(x); }
};
Then use:
der<type1, type2, type3> d;
Here's an alternative design using CRTP:
template <typename Actual, typename Base> struct FImpl : Base
{
void f(Base x) { static_cast<Actual*>(this)->p.f(x); }
};
template <typename ...T> struct der : FImpl<der, T>...
{
processor p;
};
Another solution, similar to #ArneMertz 's one, could be (but it involves several instances of processor - one per type, so could be inappropriate for some cases):
struct type1 {};
struct type2 {};
struct type3 {};
template< typename TYPE >
struct interface
{
virtual void f( TYPE ) = 0;
};
template< typename TYPE >
struct processor
{
void f( TYPE t ){ std::cout << typeid( t ).name() << std::endl; }
};
template< typename TYPE >
struct interface_impl: interface< TYPE >
{
processor< TYPE > p_;
void f( TYPE t )
{
p_.f( t );
}
};
struct final: interface_impl< type1 >, interface_impl< type2 >, interface_impl< type3 >
{
template< typename TYPE >
void f( TYPE t )
{
interface_impl< TYPE >::f( t );
}
};
This is almost the same, with one difference only - processor is added in the "middle" class. In terms of #Arne's answer:
make processor template class
processorDispatch has a member processor with the same TYPE
This:
eliminates the static_cast
simplifies the inheritance (one type vs two)
Or even processor could be defined inside interface_impl, like
template< typename TYPE >
struct interface_impl: interface< TYPE >
{
struct processor
{
void f( TYPE t ){ std::cout << typeid( t ).name(); }
} p_;
void f( TYPE t )
{
p_.f( t );
}
};