Grahalt
Grahalt

Reputation: 85

c++ template enable_if unable to match function definition to an existing declaration

I am trying to define a template member function for a template class outside of the class as well as leverage SFINAE to effectively partially overload the function. A minimal example of what I am trying is:

Test.h:

template<typename T, size_t D>
class Test
{
public:
    Test(){}
    ~Test(){}

    template<size_t W = D, typename = int*>
    void do_something(Test&);
private:
    T data[D];
};

#include <type_traits>

template<typename T, size_t D>
template<size_t W, typename std::enable_if<W == 2, int>::type* = 0>
inline void Test<T, D>::do_something(Test &)
{
    exit(2);
}

template<typename T, size_t D>
template<size_t W, typename std::enable_if<W == 3, int>::type* = 0>
inline void Test<T, D>::do_something(Test &)
{
    exit(3);
}

Main.cpp:

int main(int, char**) {
    Test<float, 2> t1;
    Test<float, 2> t2;
    t1.do_something(t2);
    return 0;
}

However this code sample produces the error: C2244 'Test::do_something': unable to match function definition to an existing declaration. If I change

template<size_t W, typename std::enable_if<W == 2, int>::type* = 0>

to

 template<size_t W, typename Type>

and remove the other definition of do_something then the code will compile with no problem so I know that enable_if is the problem. So the question is: How do I use enable_if to achieve a partial overload effect without defining the function inside the class?

Should add that I am compiling with MSVS 2015.

Upvotes: 5

Views: 1195

Answers (1)

Jarod42
Jarod42

Reputation: 217283

You have to use std::enable_if also in declaration:

template<typename T, std::size_t D>
class Test
{
public:
    template<std::size_t W, typename std::enable_if<W == 2>::type* = nullptr>
    void do_something(Test<T, W> &);

    template<std::size_t W, typename std::enable_if<W == 3>::type* = nullptr>
    void do_something(Test<T, W> &);
};



template<typename T, std::size_t D>
template<std::size_t W, typename std::enable_if<W == 2>::type*>
void Test<T, D>::do_something(Test<T, W> &)
{
    std::cout << 1 << std::endl;
}

template<typename T, std::size_t D>
template<std::size_t W, typename std::enable_if<W == 3>::type*>
void Test<T, D>::do_something(Test<T, W> &)
{
    std::cout << 2 << std::endl;
}

Demo

Upvotes: 4

Related Questions