I was trying out a way to specialize member function based on a class template parameter, without having to use SFINAE on the class (and resulting in either code duplication or creation of another class).
Since two template parameters can't be optional, and argument enable_if
is frowned upon in guidelines, so I tried out the (remaining) following 2 ways:
template <bool boolean = true>
struct sample {
constexpr typename std::enable_if<boolean, int>::type bool_check_return(
int s) const noexcept {
return s + 1;
}
constexpr typename std::enable_if<!boolean, int>::type bool_check_return(
int s) const noexcept {
return s;
}
template <typename std::enable_if<boolean, int>::type = 0>
int bool_check_template(
int s) const noexcept {
return s + 1;
}
template <typename std::enable_if<!boolean, int>::type = 0>
int bool_check_template(
int s) const noexcept {
return s;
}
};
Godbolt link
On first look, it doesn't seem obvious to me why the return type SFINAE gives the following error about "overloading is not applicable to functions differing only in return type". SFINAE should have ensured only one copy, not two.
Which part of standard am I unknowingly violating? Or is this a compiler bug? Practically, this would not be an issue in C++17 with if constexpr
(and since one form works, I can simply choose that one).
This error is present in C++11 through C++17, which gives a low probability for the compilers to be wrong about this.
error: functions that differ only in their return type cannot be overloaded
constexpr typename std::enable_if<!boolean, int>::type bool_check_return(
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
note: previous definition is here
constexpr typename std::enable_if<boolean, int>::type bool_check_return(
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
1 error generated.
There is no SFINAE involved here because bool_check_return
are not templates themselves. They are just regular overloaded functions that differ only in return type. Making them templates would solve the problem by allowing only one of them:
template<bool enabled = boolean>
constexpr typename std::enable_if<enabled, int>::type bool_check_return(
int s) const noexcept {
return s + 1;
}
template<bool enabled = boolean>
constexpr typename std::enable_if<not enabled, int>::type bool_check_return(
int s) const noexcept {
return s;
}
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