Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

enable_if with return type for class member function

Tags:

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.
like image 479
Kunal Tyagi Avatar asked Feb 16 '19 11:02

Kunal Tyagi


1 Answers

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;
}
like image 54
user7860670 Avatar answered Sep 19 '22 22:09

user7860670