Yooouxin
Yooouxin

Reputation: 33

Why SFINAE report error in function overloading

Follwing code can't compile,I just want testing SFINAE,why it can't compile?

#include <type_traits>
template<typename T>
class TestVoid {
    template<std::enable_if_t<std::is_void_v<T>> * = nullptr>
    void func() {
        std::cout << "void\n";
    }

    template<std::enable_if_t<!std::is_void_v<T>> * = nullptr>
    void func() {
        std::cout << "none void\n";
    }
};

int main() {
    TestVoid<void> t;
    return 0;
}

Upvotes: 0

Views: 58

Answers (2)

songyuanyao
songyuanyao

Reputation: 172924

The problem is the conditions of std::enable_if don't depend on template parameter of func themselves.

You might change the code to

template<typename T>
struct TestVoid {
    template<typename X = T, std::enable_if_t<std::is_void_v<X>> * = nullptr>
    void func() {
        std::cout << "void\n";
    }

    template<typename X = T, std::enable_if_t<!std::is_void_v<X>> * = nullptr>
    void func() {
        std::cout << "none void\n";
    }
};

LIVE

Upvotes: 3

Ryan Haining
Ryan Haining

Reputation: 36802

When you instantiate the class template, all of the member function declarations must be valid. In your case, one of them won't be. Instead, you can delegate func to another function template.

live link

template<typename T, std::enable_if_t<std::is_void_v<T>> * = nullptr>
void func() {
    std::cout << "void\n";
}

template<typename T, std::enable_if_t<!std::is_void_v<T>> * = nullptr>
void func() {
    std::cout << "none void\n";
}

template<typename T>
class TestVoid {
  public:
    void func_member() {
        func<T>();
    }
};

Or, if you want to keep the actual implementation of func as a member function:

live link

template<typename T>
class TestVoid {
  public:
    void func_member() {
        func<T>();
    }
  private:
    template<typename U, std::enable_if_t<std::is_void_v<U>> * = nullptr>
    void func() {
        std::cout << "void\n";
    }

    template<typename U, std::enable_if_t<!std::is_void_v<U>> * = nullptr>
    void func() {
        std::cout << "none void\n";
    }
};

Upvotes: 2

Related Questions