Let\'s say, I have six types, and they each belong in a conceptual category.
Here is a diagram that shows this:
I learned the following technique from R. Martinho Fernandes. The code shown below is written to illustrate the bare bones of the problem but you should refer to this blog post to get the full range of tricks to make it pretty.
You've already mentioned that you're running into problems because of signatures being identical. The trick is to make the types to be different.
Your second approach is close, but we can't use void
as the resulting type of the std::enable_if<>
.
Note that the following code does not compile, and specifying void
for the std::enable_if<>
does not change anything since the default is void
anyway.
#include
class A {};
class B {};
template <
typename T,
typename = typename std::enable_if::value>::type>
void F(T) {
std::cout << "A" << std::endl;
}
template <
typename T,
typename = typename std::enable_if::value>::type>
void F(T) {
std::cout << "B" << std::endl;
}
int main() {
F(A{});
F(B{});
}
The reason, as you already described is because the signatures are identical. Let's differentiate them.
#include
class A {};
class B {};
template <
typename T,
typename std::enable_if::value, int>::type = 0>
void F(T) {
std::cout << "A" << std::endl;
}
template <
typename T,
typename std::enable_if::value, int>::type = 0>
void F(T) {
std::cout << "B" << std::endl;
}
int main() {
F(A{});
F(B{});
}
Prints:
A
B
We have now differentiated the types between the 2 functions because rather than the second template parameter being a type, it is now an int
.
This approach is preferable to using std::enable_if<>
in the return type for example since constructors don't have return types, the pattern wouldn't be applicable for those.
Notes: std::is_same<>
is used with a single class to simplify the condition.