I wrote some classes based on this excellent visitor pattern described here (my implementation is a little bit different).
template<typename... Types>
class Visitable {
public:
virtual void accept(Visitor<Types...>& visitor) = 0;
};
class MyClass : public Visitable<int, string>
{
virtual void accept(Visitor<int, string>& visitor)
{
/*** my code ***/
}
};
This code above works but I would like implement MyClass like that:
class MyClass : public Visitable<int, string>
{
template<typename... Types>
virtual void accept(Visitor<Types...>& visitor)
{
/*** my code ***/
}
};
Obviously I changed the call to the accept method but I have this error: "cannot instantiate abstract class". Why in this second case, accept() is not overridden ? MyClass should be templated ?
Thanks.
Use the CRTP:
template<class D, class...Ts>
struct Visitable_CRTP : public Visitable<Ts...> {
virtual void accept(Visitor<Ts...>& visitor) override final {
return static_cast<D*>(this)->accept_impl(visitor);
}
};
class MyClass : public Visitable_CRTP<MyClass, int, string>
{
template<typename... Types>
void accept_impl(Visitor<Types...>& visitor) // not virtual
{
/*** my code ***/
}
};
Visitor_CRTP writes the glue code that attaches virtual accept to your template accept_impl.
If you want to have more than one accept method, we can do this:
template<class D, class...Visitables>
struct PolyVisitable_CRTP {};
template<class D, class...V0, class...Vs>
struct PolyVisitable_CRTP<D, Visitable<V0...>, Vs...>
Visitable_CRTP<D, V0...>,
PolyVisitable_CRTP<D, Vs...>
{};
which can be used like this:
class MyClass :
public PolyVisitable_CRTP<MyClass,
Visitable<int,double>,
Visitable<std::string, char, wchar_t>,
Visitable<>
>
{
template<typename... Types>
void accept_impl(Visitor<Types...>& visitor)
{
/*** my code ***/
}
};
and all of the Visitable bases's accepts will be routed to accept_impl.
Code not tested or compiled, probably contains tpyos.
In fact you try to implement
void VisitTable<int, string>::accept(Visitor<int, string>& visitor);
with
void MyClass::accept<int, string>(Visitor<int, string>& visitor);
In C++ it is not the same method name - one has a template qualification and the other not. Moreover template and virtual are incompatible specifiers for methods and you should have an error for
class MyClass : ... {
...
template<typename... Types>
virtual void accept(Visitor<Types...>& visitor);
};
error: templates may not be ‘virtual’
The override C++11 keyword helps to avoid such surprises.
Related
I'm trying to figure out how to give arbitrary template parameters to a class, then have that class use each of those parameters to instantiate a bass class. Something along these lines:
template<class T>
SingleParamClass;
template<class ... TYPE_LIST>
MultiParamClass : SingleParamClass<TYPE_LIST[0]>, SingleParamClass<TYPE_LIST[1]>... SingleParamClass<TYPE_LIST[N]>;
I've written it with indexing into the parameter pack just for demonstration purposes obviously.
I know how to unpack the type list, but not how to unpack it in a way that I can use it as above.
Edit:
As requested I'll expand on what I'm trying to do...
I want to make a subclass that constructs a series of pure virtual methods using the types in the variadic template params. These pure virtual methods are there for another component to call, and simultaneously forces the dev to implement those methods in the derived class.
In a world where C++ magically works the way I want, I'd do something like this:
template<class ... TYPE_LIST>
MultiParamClass {
virtual void func(TYPE_LIST[0] arg) = 0;
virtual void func(TYPE_LIST[1] arg) = 0;
...
virtual void func(TYPE_LIST[N] arg) = 0;
}
I don't know a way to do this, so I'm trying to find a way around it using subclasses, something like this:
template<class T>
SingleParamClass {
virtual void func(T arg) = 0;
}
template<class ... TYPE_LIST>
MultiParamClass : SingleParamClass<TYPE_LIST[0]>, SingleParamClass<TYPE_LIST[1]>... SingleParamClass<TYPE_LIST[N]>;
You can expand the parameter pack like so:
template<class T>
struct SingleParamClass {};
template<class ... TYPE_LIST>
struct MultiParamClass : SingleParamClass<TYPE_LIST>... {};
Perhaps try something like this:
template<class T>
class SingleParamClass
{
public:
virtual void func(T arg) = 0;
};
template<class... TYPE_LIST>
class MultiParamClass : public SingleParamClass<TYPE_LIST>...
{
};
class MyMultiParamClass : public MultiParamClass<int, double, string>
{
public:
void func(int arg) override { ... }
void func(double arg) override { ... }
void func(string arg) override { ... }
};
Online Demo
In C++ is it possible to define multiple methods based of the number of template parameters provided? Similar to how variadic functions work?
With functions I can do
template <class ...Args>
struct VariadicFunctionCallback {
typedef std::function<void(std::shared_ptr<Args>...)> variadic;
};
But what I want to know is if I could do something similar but to create multiple functions instead of multiple arguments
template <class ...FunctionArg>
class Example {
void Function(FunctionArg)...
}
Which would then allow me to do something like
template <>
class Example<int, float> {
void Function(int i) {
...
}
void Function(float f) {
...
}
}
And if this is possible what are the advantages over my current setup which is like
template<class EventType>
class EventHandler {
public:
void HandleEvent(const std::shared_ptr<EventType>& event) {
}
};
class ExampleEvent : public Event<ExampleEvent> {
};
class ExampleHandler : public EventHandler<ExampleHandler>, EventHandler<Events::ShutdownEvent> {
public:
void HandleEvent(const std::shared_ptr<ExampleEvent> &event);
void HandleEvent(const std::shared_ptr<Events::ShutdownEvent> &event);
};
--Edit--
I ended up with a mix if the two solutions.
It is probably not the best and I will continue to play around with and improve it overtime.
template <class EventType>
class BaseEventHandler {
public:
EventIdentifier GetIdentifier() const {
return EventType::GetIdentifier();
}
virtual void HandleEvent(const std::shared_ptr<EventType> &event) = 0;
};
template<class EventType, class ...EventTypes>
class EventHandler: public BaseEventHandler<EventTypes>... {
};
Which then allows me to do
class EventListener: public EventHandler<ShutdownEvent, MousePosEvent, WindowCloseRequestEvent> {
void HandleEvent(const std::shared_ptr<ShutdownEvent> &event);
void HandleEvent(const std::shared_ptr<MousePosEvent> &event);
void HandleEvent(const std::shared_ptr<WindowCloseRequestEvent> &event);
}
I suppose you can make Example a sort of recursive self-inheritancing class; something as
template <typename ...>
struct Example
{
// dummy Function() to end the recursion
void Function ()
{ }
};
template <typename T0, typename ... Ts>
struct Example<T0, Ts...> : public Example<Ts...>
{
using Example<Ts...>::Function;
void Function (T0 const &)
{ };
};
So you can write
int main ()
{
Example<int, long, float> e0;
e0.Function(0);
e0.Function(0L);
e0.Function(0.0f);
}
-- EDIT --
The OP ask
Could a specialisation then be preformed on top of this?
Do you mean something as follows?
template <typename ...>
struct Example
{
// dummy Function() to end the recursion
void Function ()
{ }
};
template <typename T0, typename ... Ts>
struct Example<T0, Ts...> : public Example<Ts...>
{
using Example<Ts...>::Function;
void Function (T0 const &)
{ };
};
template <typename ... Ts>
struct Example<float, Ts...> : public Example<Ts...>
{
void FunctionFloat (float const &)
{ };
};
int main ()
{
Example<int, long, float> e0;
e0.Function(0);
e0.Function(0L);
e0.FunctionFloat(0.0f);
//e0.Function(0.0f); // compilation error
}
This answer start's with max66's answer, more or less
We start with a class that uses recursive inheritance to implement our function. In my case, I chose operator(), and I used a variadic using declaration to bring all children operator() into scope:
namespace detail{
template<class T, class... U>
struct ExampleImpl : ExampleImpl<U>...{
using ExampleImpl<U>::operator()...;
void operator()(T _arg){/*...*/}
};
}
Where my answer diverges from max66's is in that we'll use this ExampleImpl class to compose our Example class:
template<class... T>
class Example
{
public:
template <class U>
void Function(U arg)
{
impl(arg);
}
void Function(float arg)
{
/*Your specialization code*/
}
private:
detail::ExampleImpl<T...> impl;
};
I do it this way for 2 reasons:
This inheritance is an implementation-detail and something you'd want to hide from clients.
*Now we can easily specialize our Function function for whatever type we want because we always have a choice in whether to call through to our instance of ExampleImpl or not.
Demo
If ExampleImpl needs to use member variables of your Example class, then you can either turn ExampleImpl into a full-fledged PIMPL class, or modify its constructor or operator() to accept additional arguments as a form of Dependency Injection
*You could just as easily perform full class specialization where float is one of the template parameters in the specialization, and define your own Function. Or you could use a form of tag dispatching to hide the float version unless it was in the list of template types.
Tag dispatch demonstration
I have a really ugly implementation of something that I want to refactor but I am not sure how. Here is what I have:
Some templated object
template< typename T>
class Thing { };
An interface
class IService {
public:
virtual void func(void* arg) = 0;
};
A templated class implementing it
template< typename T>
class Service< T> : public IService {
virtual void func(void* arg) {
func((Thing< T>* )arg);
}
void func(Thing< T>* arg) {
// do something with arg
}
};
The reason is that I want a non-templated IService that I can pass around. templating IService will cause massive refactor through a large code base.
So instead, I instantiate Service< T> objects, pass around the IService, and call func with templated Thing objects, which does an ugly cast to a similar function that takes the actual Thing object. Is there any clean way to achieve this without templating IService?
Edit: some more context. This is what I really want:
template<typename T>
class IService {
public:
virtual void func(Thing<T>* arg) = 0;
};
However, I cannot template IService.
Assuming that you don't want to or can't give Thing a base class, and given that a given Service<T> can only handle Things which have the same T, you could do this:
class IService {
public:
template <typename T>
void func(Thing<T>* arg) {
auto self = dynamic_cast<Service<T>*>(this);
if (self) {
self->func(arg);
} else {
// decide how to handle this error
}
}
};
func would not be virtual. It is just a template policy that deriving from IService needs to have a func(Thing<T>*) method.
Maybe some interface for the Thing would do the trick?
class IThing { };
template< typename T>
class Thing: public IThing { };
class IService {
public:
virtual void func(IThing* arg) = 0;
};
template< typename T>
class Service: public IService {
virtual void func(IThing* arg) {
Thing<T> *thing = dynamic_cast<Thing<T> *>(arg);
if (thing) {
// implementation
}
}
};
I'm assuming you want to type-erase Thing's <T> template parameter through the use of a non-templated IService class and that you do not care about T in the implementation of IService. I am not sure these assumption are correct, but here's a possible solution.
I'm also assuming that having virtual dispatch inside Thing suffice in your use case.
// Create a `ThingBase` class to "type-erase" `Thing`'s
// template parameter. `ThingBase` should contain your
// `func`, as `virtual`.
struct ThingBase
{
virtual void func();
};
// Your `Thing<T>` class should override `func`
template <typename T>
struct Thing : ThingBase
{
void func() override { /* ... */ }
};
// Your `IService` now only needs to be as follows:
struct IService
{
void func(ThingBase& x)
{
x.func();
}
};
The problem is that template <typename T> virtual void foo() is illegal, and I'm trying to use the visitor pattern to workaround that (which is known to work in general). However the derived classes of Base are template classes, and now I'm running into the virtual template problem within the visitor classes. How to work around this?
struct Base {
// template <typename T> virtual void foo() = 0; // illegal
virtual void foo (class Visitor& visitor) = 0; // The attempted solution
};
template <typename D>
struct Derived : Base {
virtual void foo (Visitor&) override;
};
struct Visitor {
//template <typename D> // same problem again!
virtual void visit (Derived<D>*) const = 0;
};
template <typename T, typename D>
struct FooVisitor : Visitor {
virtual void visit (Derived<D>*) const override {/*Do whatever with T*/}
};
template <typename D>
void Derived<D>::foo (Visitor& visitor) {visitor.visit(this);}
With all solutions, let's assume there shall be about one hundred values for D, with new D classes being introduced constantly. And each will use D in the same way. For simplicity, let's assume each visit function will use D with
func<D>();
where
template <typename D> void Base::func();
is some helper function in Base.
Here is a solution that might work. Note that the assumption here is that you only make invocations with the right type:
struct Base {
virtual void foo(struct Visitor& visitor) = 0;
};
template <typename D>
struct Derived : Base {
virtual void foo (Visitor&v) override;
};
struct Visitor {
virtual ~Visitor() {} // Make this class polymorphic.
};
template <typename D>
struct Visitor_tmpl : public Visitor {
virtual void visit (Derived<D>*) const {/*Do whatever with T*/}
};
template <typename T, typename D>
struct FooVisitor : Visitor_tmpl<D> {
virtual void visit (Derived<D>*) const override {/*Do whatever with T*/}
};
template <typename D>
void Derived<D>::foo(Visitor&v) {
// In this function, D has been bound now to a specific type, so we downcast.
// It will throw an exception if not the right type.
dynamic_cast<Visitor_tmpl<D> &>(v).visit(this);
}
int main() {
Derived<int> d;
FooVisitor<double, int> v;
d.foo(v);
}
One possible solution was mentioned by Jarod42, namely to specify all possibly occuring types. Usually, however, you want to give a standard implementation taking a Base* as well, and overload this only when required.
struct Type1 {};
//...
struct TypeN {};
struct Visitor
{
virtual ~Visitor() {}
virtual void visit (Base*) const = 0;
virtual void visit (Derived<Type1>* d) const { visit(static_cast<Base*>(d)); };
//...
virtual void visit (Derived<TypeN>* d) const { visit(static_cast<Base*>(d)); };
};
struct FooVisitor : public Visitor
{
virtual void visit (Base* base) const override
{
std::cout<<"visiting base class."<<std::endl;
}
//further definitions for those types that require a special implementation
virtual void visit (Derived<TypeN>* d) const override
{
std::cout<<"visiting class of type Derived<TypeN>."<<std::endl;
}
};
DEMO
EDIT: Here is another possibility using basic double dispatch:
struct Visitor
{
virtual ~Visitor() {}
virtual void visit (Base*) const = 0;
};
struct FooVisitor : public Visitor
{
virtual void visit (Base* base) const override
{
if(Derived<TypeN>* d = dynamic_cast<Derived<TypeN>*>(base))
{
std::cout<<"visiting class of type Derived<TypeN>."<<std::endl;
}
else
{
std::cout<<"visiting base class."<<std::endl;
}
}
};
It releases you from declaring each possible variable type in the base class, but is probably less efficient than the previous solution.
This brute-force approach has some other disadvantages, which are collected in chapter 11 of Alexandrescu's book. You can also read there how to overcome these disadvantages by using a static dispatcher. Basically there you just enter once the types you want to consider for dispatching, and let the code create the above logic.
DEMO
I'm writing a wrapper for some benchmark code and want to execute the same code for every templated class type in an already templated function.
There is the benchmark class:
template<class T>
class Benchmark : public Interface, public T {
virtual void Execute();
}
And as class T I want to use a type that is basically only there for initializing class variables e.g.
template<class S>
struct GenericBench {
GenericBench();
S var1, var2, var3;
};
The question now: is it somehow possible to define a specialized function Execute for every mutation of GenericBench for this kind of class inheritance constelation?
template<>
void Benchmark<GenericBench>::Execute() {
// my benchmark code
}
A main call would then look something like this:
myBench->Execute<GenericBench<int>>();
The following code compiled and linked in g++
struct Interface { };
template<class T>
class Benchmark: public Interface, public T {
public:
virtual ~Benchmark() { }
virtual void Execute();
};
template<class S>
struct GenericBench {
GenericBench() { }
S var1, var2, var3;
};
// Specialization of the class
template<class S>
class Benchmark<GenericBench<S> >: public Interface, public GenericBench<S> {
public:
virtual ~Benchmark() { }
virtual void Execute() {
// do things
}
};
int main(int argc, char **argv) {
Benchmark<GenericBench<int> > myBench;
myBench.Execute();
}
Since you said that you want to define specialized responses on basis of type you are working on... making function template and then specializing it will help.
Following is an examples
(Apologies for not using example u provided.. I just want to show the approach. Let me know if it works for you)
template <class S> class myData {
public:
};
namespace mySpecializedFunction {
template<class P> void someFunction(P check) {std::cout<<"3333\n";return;}
template<> void someFunction(myData<int> check) {std::cout<<"4444\n";return;}
template<> void someFunction(myData<float> check) {std::cout<<"5555\n";return;}
}
template <class T> class myClass: public T {
public:
template <class Q> void someFunction( Q check) { mySpecializedFunction::someFunction(check); return ; }
};
And Using it like this...
myData<int> d1;
myData<float> d2;
myClass< myData<int> > c1;
c1.someFunction(d1);
myClass< myData<float> > c2;
c2.someFunction(d2);