Let's say, I have six types, and they each belong in a conceptual category.
Here is a diagram that shows this:
Or Perhaps a more specific example for you:
I want to write two functions that will handle all 6 types.
Types in "Category 1" get handled a certain way, and types in "Category 2" get handled a different way.
Let's get into the code. First, I'll create the six types.
//Category 1 Types
class Type_A{};
class Type_B{};
class Type_C{};
//Category 2 Types
class Type_D{};
class Type_E{};
class Type_F{};
Next, I'll create two type traits so that the category of the type can be discovered at compile time.
/* Build The Category 1 Type Trait */
//Type_A Type Trait
template <typename T>
struct Is_Type_A {
static const bool value = false;
};
template <>
struct Is_Type_A<Type_A> {
static const bool value = true;
};
//Type_B Type Trait
template <typename T>
struct Is_Type_B {
static const bool value = false;
};
template <>
struct Is_Type_B<Type_B> {
static const bool value = true;
};
//Type_C Type Trait
template <typename T>
struct Is_Type_C {
static const bool value = false;
};
template <>
struct Is_Type_C<Type_C> {
static const bool value = true;
};
//Category 1 Type Trait
template <typename T>
struct Is_Type_From_Category_1 {
static const bool value = Is_Type_A<T>::value || Is_Type_B<T>::value || Is_Type_C<T>::value;
};
/* Build The Category 2 Type Trait */
//Type_D Type Trait
template <typename T>
struct Is_Type_D {
static const bool value = false;
};
template <>
struct Is_Type_D<Type_D> {
static const bool value = true;
};
//Type_E Type Trait
template <typename T>
struct Is_Type_E {
static const bool value = false;
};
template <>
struct Is_Type_E<Type_E> {
static const bool value = true;
};
//Type_F Type Trait
template <typename T>
struct Is_Type_F {
static const bool value = false;
};
template <>
struct Is_Type_F<Type_F> {
static const bool value = true;
};
//Category 1 Type Trait
template <typename T>
struct Is_Type_From_Category_2 {
static const bool value = Is_Type_D<T>::value || Is_Type_E<T>::value || Is_Type_F<T>::value;
};
Now that I have two type traits to distinguish what category each of the six types fall into, I want to write two functions. One function will accept everything from Category 1, and the other function will accept everything from Category 2. Is there a way to do this without creating some kind of dispatching function? Can I find a way to have only two functions; one for each category?
EDIT: I have tried to use enable_if like this, but such an attempt will result in a compiler error.
//Handle all types from Category 1
template<class T ,class = typename std::enable_if<Is_Type_From_Category_1<T>::value>::type >
void function(T t){
//do category 1 stuff to the type
return;
}
//Handle all types from Category 2
template<class T ,class = typename std::enable_if<Is_Type_From_Category_2<T>::value>::type >
void function(T t){
//do category 2 stuff to the type
return;
}
Edit 2: I've tried the code provided in the link, but this isn't a yes or no decision on whether or not to call the function. It's which function do I call, given two type traits. This would be a redefinition error.
//Handle all types from Category 2
template<class T, class dummy = typename std::enable_if< Is_Type_From_Category_1<T>::value, void>::type>
void function(T t){
//do category 1 stuff to the type
return;
}
//Handle all types from Category 2
template<class T, class dummy = typename std::enable_if< Is_Type_From_Category_2<T>::value, void>::type>
void function(T t){
//do category 2 stuff to the type
return;
}
Two functions signatures are not allowed to differ only by the default value of a template parameter. What would happen if you explicitly called function< int, void >
?
Usual usage of enable_if
is as the function return type.
//Handle all types from Category 1
template<class T >
typename std::enable_if<Is_Type_From_Category_1<T>::value>::type
function(T t){
//do category 1 stuff to the type
return;
}
//Handle all types from Category 2
template<class T >
typename std::enable_if<Is_Type_From_Category_2<T>::value>::type
function(T t){
//do category 2 stuff to the type
return;
}