I have a class which returns the specific device based on runtime.
struct ComponentDc;
struct ComponentIc;
typedef Device<ComponentDc> DevComponentDc;
typedef Device<ComponentIc> DevComponentIc;
template<class Component>
class Device{
Device<Component>* getDevice() { return this; }
void exec() { }
};
In exec()
, I'd like to print "Hello" if the component type is ComponentDc
and world if it is ComponentIc
. Also, these are the only two types with which Device can be created.
How do I do this ?
You have two classic possibilities.
First, use two global function overloads, one for ComponentDc
, one for ComponentIc
:
void globalExec(ComponentDc) { std::cout << "Hello"; }
void globalExec(ComponentIc) { std::cout << "World"; }
void Device<Component>::exec() { globalExec(Component); }
Second, use traits-class: pure template class with no fields and with different typedefs and only static functions as methods. This class has own specializations for different possible argument types.
template<Component> class DeviceTraits {};
template<> class DeviceTraits<ComponentDc> {
static std::string getMessage() { return "Hello"; }
};
template<> class DeviceTraits<ComponentIc> {
static std::string getMessage() { return "World"; }
};
void Device<Component>::exec() {
std::cout << DeviceTraits<Component>::getMessage();
}
The advantage of using traits classes is that you don't have to spoil your global namespace with several functions.
About partially specializing the Device
class itself - it is not always possible, and it is considered more convenient to move any template-argument-specific code into traits class.
This is the classic approach used in STL. Alternatively, you can use boost::enable_if
or std::enable_if
(for the latest compilers).
You could instantiate template explicitly:
template<> class Device<ComponentDc> {
...
void exec() { cout << "Hello"; }
};
The same goes for Device<ComponentIc>
.
Also, if you want to restrict template parameters to a specific set, you should think of inheritance or composition instead of templates.
You can also use boost::enable_if
http://www.boost.org/doc/libs/1_53_0/libs/utility/enable_if.html http://www.boost.org/doc/libs/1_44_0/libs/type_traits/doc/html/boost_typetraits/reference/is_same.html
void Device<Component>::exec(boost::enable_if< boost::is_same<Component,ComponentDc> >* enabler = 0)
{
}
void Device<Component>::exec(boost::enable_if< boost::is_same<Component,ComponentIc> >* enabler = 0)
{
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With