问题
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?
回答1:
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 */ }
回答2:
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>{}); } };
来源:https://stackoverflow.com/questions/47935497/how-to-enable-member-function-using-boolean-template-parameter