4

I have a function that is overloaded for many types. But my current problem is due to that (LWS here : lws) :

#include <iostream>
#include <string>
#include <sstream>
#include <type_traits>

// First version
template<typename T, class = typename std::enable_if<std::is_fundamental<T>::value>::type> 
std::string f(const T& x)
{
    return std::to_string(x);
}

// Second version
template<typename... T> 
std::string f(const std::tuple<T...>& x)
{
    return std::to_string(sizeof...(T)); // It's just an example here
}

// Third version
template<typename T, class = typename std::enable_if<!std::is_fundamental<T>::value>::type, class = void> 
std::string f(const T& x)
{
    std::ostringstream oss;
    oss<<x;
    return oss.str();
}

// Main
int main(int argc, char* argv[])
{
   std::cout<<f(42)<<std::endl;
   std::cout<<f(std::string("Hello World"))<<std::endl;
   std::cout<<f(std::tuple<int, int, int, int, int, int>(4, 8, 15, 16, 23, 42))<<std::endl;
   return 0;
}

My problem is that when we call f() for a std::tuple, the third version is executed and not the second one.

How to solve this problem (a solution would be to allow the third version only for types where << is defined, but I don't know how to do that, and if this is the best way to solve the problem) ?

Vincent
  • 57,703
  • 61
  • 205
  • 388
  • I'm not so familiar with the new C++11 stuff, but I guess you need to extend the static check `std::is_fundamental` with checking if a `std::ostream& operator<<(std::ostream& os, const & T)` is available. – πάντα ῥεῖ Oct 24 '12 at 19:23
  • http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error (short: SFINAE) – tstenner Oct 24 '12 at 19:28
  • @g-makulik: checking if that exists is much harder than you'd think. – Mooing Duck Oct 24 '12 at 19:40
  • @MooingDuck Just for curiosity do you have a pointer how to do it? I've been using static checks for concept validation so far (generating compilation error), not for specialization selection, but shouldn't that work similarly? – πάντα ῥεῖ Oct 24 '12 at 20:19
  • @g-makulik: generating a compilation error is _easy_. Specialization selection is not similar at all, and quite complicated. See the SFINAE link that tstenner posted. – Mooing Duck Oct 24 '12 at 20:33

1 Answers1

5

Your only problem is that you forgot to #include <tuple>, which is shown in the error on LWS. Here's a fixed version that compiles correctly. The second overload is always a better match than the third one since it's more specialized according to partial ordering rules.

If you still want to know how to check for a functions existence that triggers SFINAE if it's not there, check this answer of mine on a question dedicated to that topic. :) It even has an example that pretty much matches what you want.

Community
  • 1
  • 1
Xeo
  • 129,499
  • 52
  • 291
  • 397