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