I'm trying to use std::enable_if
and SFINAE to switch out the implementation of a class template's method based purely on the template parameters of the class. Example:
#include <type_traits>
template<class T1, class T2>
class Foo {
template<class InnerT, class ... Args>
typename std::enable_if<std::is_same<T1, T2>::value, void>::type
bar(InnerT param) {};
template<class InnerT, class ... Args>
typename std::enable_if<!std::is_same<T1, T2>::value, void>::type
bar(InnerT param) {};
};
int main() {
Foo<int, int> f;
}
Here, bar()
should behave differently based on whether T1
and T2
are the same type or not. However, this code does not compile. Neither GCC nor clang tell me anything useful. I suspect the problem is that the std::enable_if
condition does not depend on the parameters of bar()
, i.e., not on its immediate context as specified in paragraph 17.8.2, point 8, of the standard.
This assumption is supported by the fact that this code compiles fine:
#include <type_traits>
class DummyClass {};
template<class T1, class T2>
class Foo {
template<class InnerT, class ... Args>
typename std::enable_if<std::is_same<T1, T2>::value ||
std::is_same<InnerT, DummyClass>::value, void>::type
bar(InnerT param) {};
template<class InnerT, class ... Args>
typename std::enable_if<!std::is_same<T1, T2>::value ||
std::is_same<InnerT, DummyClass>::value, void>::type
bar(InnerT param) {};
};
int main() {
Foo<int, int> f;
}
Now the expression inside the std::enable_if
depends on the "immediate context", namely InnerT
, even though that part of the expression always evaluates to false
.
It looks like I can use this as a workaround, but that feels really hacky and ugly. How do you solve this problem "correctly"? A thought I had was to add an additional template parameter (call it DummyType
) to bar()
, which defaults to e.g. DummyType = T1
, and then check std::is_same<DummyType, T2>
, but the fact that bar()
takes a parameter pack makes this impossible (or does it…?)
bar()
into a wrapper that usesif constexpr
to invoke one of the two actual alternate methods.