Search code examples
c++templatesoverloadingsfinaetype-traits

Why does this simple use of SFINAE & type traits to overload a function template leads to ambiguous call?


I'm trying to use type traits to provide a couple of overloads for a specific function, so that I don't have to specify the template parameter when calling said function, and it can work for any data type and different types of containers:

#include <type_traits>
#include <vector>
#include <initializer_list>

template< typename T, typename = std::enable_if< std::is_arithmetic< T >::value > >
bool myFunction(const std::vector< T >& data) {
    // ...
    return true;
}


template < typename T, typename = std::enable_if< !std::is_arithmetic< T >::value >, typename = void >
bool myFunction(const std::vector< T >& data) {
    // ...
    return true;
}


template< typename T >
bool myFunction(const std::initializer_list< T >& data) {
    return myFunction< T >(std::vector< T >(data));
}


int main(int argc, char const *argv[]) {
    std::vector< float > data = { };

    myFunction(data);  // error: call of overloaded ‘myFunction(std::vector<float>&)’ is ambiguous

    return 0;
}

However, when trying to compile this code I get an error complaining that the call is ambigous. What exactly am I missing here? Shouldn't the second template argument ensure that for any T, only a single myFunctionis declared?


Solution

  • This should be std::enable_if_t not std::enable_if. Or since you tagged C++11, you can do std::enable_if<...>::type

    std::enable_if<false> is not a substitution failure, only std::enable_if<false>::type is.