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
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
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();
}
};
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);
I'm trying to create a class which will contain a map of type_index keys mapped to pointers of each type passed as a template argument. This would allow me to specify a series of types my class will rely on in it's declaration.
I've done a bit of research but can only seem to find ways to unpack arguments, rather than types. I'm new to this subject, and would appreciate any clarification on terminology, or references to relevant text.
template <typename T>
T* SomeFakeFactoryGetter() { return new T(); }
template <class... Injected>
class UtilityProvider
{
public:
template <class U>
U* GetUtility()
{
std::type_index idx = std::type_index(typeid(U));
assert(_injectedClasses.find(idx) != _injectedClasses.end());
return reinterpret_cast<U*>(_injectedClasses[idx]);
}
// **
// How would I *unpack* all types for use as indices into my map?
// ( I realise this function is not what I want.)
template <Injected... C>
void Unpack()
{
_injectedClasses[std::type_index(typeid(C))] = SomeFakeFactoryGetter<C>();
}
private:
typedef std::unordered_map<std::type_index, void*> InjectedMap;
InjectedMap _injectedClasses;
};
class Bar{ public: void A() { printf("Hello bar"); } };
class Baz{ public: void B() { printf("Hello baz"); } };
class Nope {};
class Foo : public UtilityProvider<Bar, Baz>
{
public:
Foo()
{
GetUtility<Bar>()->A();
GetUtility<Nope>(); // Fail. User must specify which utilities this class will use.
}
};
What I've done in this situation is to create a dummy function to expand these expressions into, but it looks quite hideous:
template <int ... Dummies>
void dummy(int&& ...){}
template <class ... C>
void Unpack()
{
dummy(((_injectedClasses[std::type_index(typeid(C))] =
SomeFakeFactoryGetter<C>()), 0)...);
}
Note that in your case I think you'll be better off with using insert with an initializer_list:
template <class ... C>
void Unpack()
{
_injectedClasses.insert({std::make_pair(std::type_index(typeid(C)),
SomeFakeFactoryGetter<C>())...});
}
I couldn't find a direct mention of this but I believe there is an important difference between the two methods, in case you didn't already know. insert will not override existing key-value pairs, whereas operator[] will. This can affect which method you should use if if this is important to you.
An alternative approach:
template <typename ... C> struct Unpacker;
template <typename Tail, typename ... Queue>
struct Unpacker<Tail, Queue...>
{
void operator () (InjectedMap& injectedClasses) const
{
_injectedClasses[std::type_index(typeid(Tail))] = SomeFakeFactoryGetter<Tail>();
Unpacker<Queue...>()(injectedClasses);
}
};
template <>
struct Unpacker<>
{
void operator () (InjectedMap& injectedClasses) const {}
};
class FooInterface {
virtual void toggle() = 0;
};
template <class TYPE, class CONFIG>
class Foo : public FooInterface {
virtual void toggle();
TYPE value_;
};
template <>
void Foo<bool, class CONFIG>::toggle() {
if (CONFIG::canToggle())
value_ = !value_;
}
struct MyConfig {
static bool canToggle() {
return false;
}
};
int main() {
Foo<bool, MyConfig> foo;
}
That's an accurate approximation of what I'm dealing with. I basically want to have a specialized method for dealing with a TYPE, while keeping the CONFIG generic. So, for example, I might have a dozen different Foo::toggle() methods with specialized code handling specific TYPEs, but what's used from CONFIG will be consistent across all of those methods.
The problem is the previous code doesn't compile, along with several different combinations, and I'd appreciate some help finding a different solution or some workaround to make the current one work.
Edit: I should note that the previous code works without the CONFIG template parameter.
You need to partially specialise the whole class. You can't specialise individual member functions.
template <class CONFIG>
class Foo<bool, CONFIG> : public FooInterface
{
virtual void toggle();
bool value_;
};
template <class CONFIG>
inline void Foo<bool, CONFIG>::toggle()
{
if (CONFIG::canToggle())
value_ = !value_;
}
dispatch
template<class CONFIG, class C>
void toggle_impl(type<bool>, C &c) {
if (CONFIG::canToggle())
c.value_ = !c.value_;
}
template <class TYPE, class CONFIG>
class Foo : public FooInterface {
virtual void toggle() {
toggle_impl<CONFIG>(type<TYPE>(), *this);
}
TYPE value_;
};