I would like a class to have two different implementations of push
, and choose based on a boolean template argument. I tried using the SFINAE principle as described in this answer, like so:
template<class T, bool foo=true>
class Bar {
template <>
typename std::enable_if<foo>::type
push(const T& value) { /* one implementation */}
template <>
typename std::enable_if<!foo>::type
push(const T& value) { /* another implementation */ }
}
however, I am getting an error of "cannot specialize a function push
within class scope" under gcc, and I do not understand why. Although my code is not exactly like that in the linked answer, it seems very similar and I can't spot the critical difference.
I also tried using a syntax similar to that suggested in this answer but it is also not working (the error is "class member cannot be redeclared" instead):
template <bool enable=foo>
typename std::enable_if<enable>::type
push(const T& value) { /* one implementation */}
template <bool enable=!foo>
typename std::enable_if<enable>::type
push(const T& value) { /* another implementation */ }
How can I accomplish this?
Firstly, SFINAE works with function templates overloading; so you should go with the 2nd approach. But you declare two overloads with same signature; note that the default argument of template parameter doesn't belong to the signature.
Change it to
template <bool enable=foo>
typename std::enable_if<enable>::type
// ~~~~~~
push(const T& value) { /* one implementation */}
template <bool enable=foo>
typename std::enable_if<!enable>::type
// ~~~~~~~
push(const T& value) { /* another implementation */ }
As alternatives:
if constexpr
in C++17:
template<class T, bool foo=true>
class Bar {
public:
void push(const T& value) {
if constexpr(foo) {
/* one implementation */
} else {
/* another implementation */
}
}
};
Tag dispatching:
template<class T, bool foo=true>
class Bar {
void push_impl(const T& value, std::true_type) {
/* one implementation */
}
void push_impl(const T& value, std::false_type) {
/* another implementation */
}
public:
void push(const T& value) {
push_impl(value, std::integral_constant<bool, foo>{});
}
};
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