2

Very often I used SFINAE before but I have a very very simple example I can't get to run today.

class X
{
    public:
        template <typename CHECK, typename = typename std::enable_if< std::is_floating_point<CHECK>::value, void>::type >
            void Do()
            {
                std::cout << "yes" << std::endl;
            }

        template <typename CHECK, typename = typename std::enable_if< !std::is_floating_point<CHECK>::value, void>::type>
            void Do()
            {
                std::cout<< "no" << std::endl;
            }

};

int main()
{
    X x;
    x.Do<float>();
}

Error:

src/main.cpp:20:18: error: 'template void X::Do()' cannot be overloaded

src/main.cpp:14:18: error: with 'template void X::Do()' void Do()

I want to disable any overload with enable_if but it doesn't work...

Any idea what today I did wrong?

Klaus
  • 24,205
  • 7
  • 58
  • 113

2 Answers2

3

The two functions have the same sigature, so you get a redefinition error. Try it with the following instead, which uses default arguments:

#include <type_traits> 
#include <iostream>

class X
{
    public:
        template <typename CHECK, std::enable_if_t< std::is_floating_point<CHECK>::value>* =nullptr >
            void Do()
            {
                std::cout << "yes" << std::endl;
            }

        template <typename CHECK, std::enable_if_t< !std::is_floating_point<CHECK>::value>* =nullptr>
            void Do()
            {
                std::cout<< "no" << std::endl;
            }

};

int main()
{
    X x;
    x.Do<float>();
}

DEMO

See also the answers here and here.

Community
  • 1
  • 1
davidhigh
  • 14,652
  • 2
  • 44
  • 75
  • Thanks. But I have a big misunderstanding on how enable_if works. I thought enable_if will result in a "compile error" if the condition is false and as a result the template will be "disabled" and as a result of that I only got one instance which can't be an overload. But now I have an overload and SFINAE seems not to work. Can you give a explanation on that? – Klaus Jul 21 '15 at 12:48
0

Another syntax which compiles and works is to move the enable_is as the return type:

class X
{
public:
    template <typename CHECK >
    typename std::enable_if< std::is_floating_point<CHECK>::value, void>::type Do()
    {
        std::cout << "yes" << std::endl;
    }

    template <typename CHECK>
    typename std::enable_if< !std::is_floating_point<CHECK>::value, void>::type Do()
    {
        std::cout << "no" << std::endl;
    }

};

int main()
{
    X x;
    x.Do<float>();
    getchar();
}
David Haim
  • 25,446
  • 3
  • 44
  • 78