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_;
};
Related
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();
}
};
I would like to define a template class with specialization of some methods for different types.
template <typename T>
class Handler {
public:
void method1() { method2(); }
protected:
void method2();
}
Then in the implementation file:
template <> Handler<int>::method2() { doSomething(); }
template <> Handler<float>::method2() { doSomethingElse(); }
template <> Handler<ClassB>::method2() { doSomethingDifferent(); }
So far, everything works ok.
Now I would like to define some new classes derived from ClassB, and use the template specialization on objects of these classes. Of course it compiles but does not link, because the specialization for each subclass is missing.
Is there a way to use the template for these, for example using SFINAE?
I often find overloading on a type tag a good alterantive to specialization:
namespace {
template<class T> struct Type { using type = T; }; // Or boost::type<T>
template<class T> struct TypeTag { using type = Type<T>; };
struct ClassB {};
template <typename T>
class Handler {
public:
void method1() {
method2(typename TypeTag<T>::type{}); // Call an overloaded function.
}
protected:
void method2(Type<int>) { std::printf("%s\n", __PRETTY_FUNCTION__); }
void method2(Type<float>) { std::printf("%s\n", __PRETTY_FUNCTION__); }
void method2(Type<ClassB>) { std::printf("%s\n", __PRETTY_FUNCTION__); }
};
// Somewhere else.
struct ClassC : ClassB {};
template<> struct TypeTag<ClassC> { using type = Type<ClassB>; };
} // namespace
int main(int ac, char**) {
Handler<ClassB> b;
b.method1();
Handler<ClassC> c;
c.method1();
}
Outputs:
void {anonymous}::Handler<T>::method2({anonymous}::Type<{anonymous}::ClassB>) [with T = {anonymous}::ClassB]
void {anonymous}::Handler<T>::method2({anonymous}::Type<{anonymous}::ClassB>) [with T = {anonymous}::ClassC]
First:
template <class T,class=void>
class Handler
then use SFINAE to create a specialization:
template <class T>
class Handler<T,std::enable_if_t<test>>
Now, have that specialization either include its implementation in its body, or inherit from an implementation type (non-template) and implement that in the impl file.
For your puroposes, the test might be is base of.
Your int impl now needs a ,void parameter added.
You can also use a traits class to do conditional mapping.
I'm currently playing around with templates in C++ and got stuck with template template parameters.
Lets say I have the following classes:
template<typename T>
struct MyInterface
{
virtual T Foo() = 0;
}
class MyImpl : public MyInterface<int>
{
public:
int Foo() { /*...*/ }
};
template< template<typename T> typename ImplType>
class MyHub
{
public:
static T Foo()
{
ImplType i;
return i.Foo();
}
private:
MyHub() { }
~MyHub() { }
};
In essence I would like to have a static class like MyHub that accepts an implementation of MyInterface and provides certain static methods to use them like static T Foo().
Then I tried to use MyHub:
int main()
{
int i = MyHub<MyImpl>::Foo();
return 0;
}
Unfortunately I always end up getting an error saying that the type T (of static T Foo() in MyHub) does not name a type.
I would expect that it works because
the template parameter of the template parameter Impl is named T
MyHub is a templated class with one template parameter and contains a method Foo
So far I couldn't find a solution for this after digging through documentations and google results so I hope some of you can help me.
You can use typedefs. Also, since your implementation classes are not template class, there is no need for template template parameters.
#include <iostream>
#include <string>
template<typename T>
struct MyInterface
{
virtual T Foo() = 0;
typedef T Type;
};
class MyIntImpl : public MyInterface<int>
{
public:
int Foo() { return 2; }
};
class MyStringImpl : public MyInterface<std::string>
{
public:
std::string Foo() { return "haha"; }
};
template<class ImplType>
class MyHub
{
public:
static typename ImplType::Type Foo()
{
ImplType i;
return i.Foo();
}
private:
MyHub() { }
~MyHub() { }
};
int main()
{
std::cout << MyHub<MyIntImpl>::Foo() << "\n"; // prints 2
std::cout << MyHub<MyStringImpl>::Foo() << "\n"; // print haha
return 0;
}
Here is an example.
MyImpl is not a class template; so can't be passed as the template parameter of MyInterface.
You could change your MyInterface, MyImpl and MyHub classes to:
template<typename T>
class MyInterface{
public:
virtual T foo() = 0;
};
class MyImpl: public MyInterface<int>{
public:
using value_type = int;
value_type foo(){ return 1; /* dummy */ }
};
template<typename Impl, typename = std::enable_if_t<std::is_base_of<Impl, MyInterface<typename Impl::value_type>>::value>>
class MyHub{
public:
static auto foo(){
static Impl i;
return i.foo();
}
};
Which lets you use it the same way you are in your example.
The std::is_base_of check might be a little unnecessary in this case; but, this way you can't accidentally pass in another class that isn't derived from MyInterface with a method foo().
The STL uses value_type as a place holder for the underlying type of a template class. You could possibly do the same for your solution.
template<typename T>
struct MyInterface
{
typedef T value_type;
virtual T Foo() = 0;
}
class MyImpl : public MyInterface<int>
{
public:
int Foo() { /*...*/ }
};
template<typename ImplType>
class MyHub
{
public:
static typename ImplType::value_type Foo()
{
ImplType i;
return i.Foo();
}
private:
MyHub() { }
~MyHub() { }
};
Also note that in c++14, typename ImplType::value_type can be replaced by auto:
static auto Foo()
{
ImplType i;
return i.Foo();
}
The names of template parameters of template template parameters are effectively a purely documentational construct—they don't get included in the containing template's scope.
There's good reason for that: there is nothing to whcih they could refer in the containing template. When you have a template template parameter, you must pass a template as the argument to it, and not an instantiation of a template. In other words, you're passing a template without arguments as the argument.
This means your code is simply wrong—you're using MyImpl as an argument for MyHub, but MyImpl is a class. MyHub expects a template, not a class. The correct instantiation of MyHub would be MyHub<MyInterface>. Not that there are no template arguments after this use of MyInterface; we are passing in the template itself, not an instantiation of it.
Template template parameters are used rather rarely in practice. You only use them if you want to instantiate the parameter template with your own types. So I would expect your MyHub code to do something like this:
template <template <class> class ImplTemplate>
struct MyHub
{
typedef ImplTemplate<SomeMyHub_SpecificType> TheType;
// ... use TheType
};
This doesn't seem to be what you want to do. I believe you want a normal type template parameter, and provide a nested typedef for its T. Like this:
template <class T>
struct MyInterface
{
typedef T ParamType; // Added
virtual T Foo() = 0;
};
template<class ImplType>
class MyHub
{
typedef typename ImplType::ParamType T;
public:
static T Foo()
{
ImplType i;
return i.Foo();
}
private:
MyHub() { }
~MyHub() { }
};
int main()
{
int i = MyHub<MyImpl>::Foo();
return 0;
}
I have a template class Field<T> which inherits from a non-template abstract base class AbstractField to be able to store all different kinds of Field<T> * types in a std::vector<AbstractField *>. My setup is as follows:
#include <vector>
class AbstractField
{
public:
virtual ~AbstractField() {};
// Something similar to: template<class T> T getValue() const; ?
};
template<class T>
class Field : public AbstractField
{
private:
T d_;
public:
Field(T d) : d_(d) {}
T getValue() const { return d_; }
};
int main()
{
AbstractField *f = new Field<double>(0.1);
// How to call: f->getValue(); ?
return 0;
}
I was wondering what would be the most natural way to call f->getValue() since I can't use a virtual template member function in the AbstractField class. As far as possible, I would prefer not using boost. Any hints are welcome!
EDIT:
Corrected std::vector<Field<T> > to std::vector<AbstractField *>. Sorry for the confusion.
Maybe this:
template <typename> struct Field;
struct AbstractField
{
virtual ~AbstractField() {}
template <typename T> T getValue()
{
return dynamic_cast<Field<T>&>(*this)->get();
}
};
template <typename T> struct Field : AbstractField
{
T & get();
// ...
};