In this answer I define a template based on the type's is_arithmetic property:
template<typename T> enable_if_t<is_arithmetic<T>::value, string> stringify(T t){
    return to_string(t);
}
template<typename T> enable_if_t<!is_arithmetic<T>::value, string> stringify(T t){
    return static_cast<ostringstream&>(ostringstream() << t).str();
}
dyp suggests that rather than the is_arithmetic property of the type, that whether to_string is defined for the type be the template selection criteria. This is clearly desirable, but I don't know a way to say:
If
std::to_stringis not defined then use theostringstreamoverload.
Declaring the to_string criteria is simple:
template<typename T> decltype(to_string(T{})) stringify(T t){
    return to_string(t);
}
It's the opposite of that criteria that I can't figure out how to construct. This obviously doesn't work, but hopefully it conveys what I'm trying to construct:
template<typename T> enable_if_t<!decltype(to_string(T{})::value, string> (T t){
    return static_cast<ostringstream&>(ostringstream() << t).str();
}
                Using Walter Brown's void_t:
template <typename...>
using void_t = void;
It's very easy to make such a type trait:
template<typename T, typename = void>
struct has_to_string
: std::false_type { };
template<typename T>
struct has_to_string<T, 
    void_t<decltype(std::to_string(std::declval<T>()))>
    > 
: std::true_type { };
                        First, I think SFINAE should usually be hidden from interfaces. It makes the interface messy. Put the SFINAE away from the surface, and use tag dispatching to pick an overload.
Second, I even hide SFINAE from the traits class.  Writing "can I do X" code is common enough in my experience that I don't want to have to write messy SFINAE code to do it.  So instead I write a generic can_apply trait, and have a trait that SFINAE fails if passed the wrong types using decltype.
We then feed the SFIANE failing decltype trait to can_apply, and get out a true/false type depending on if the application fails.
This reduces the work per "can I do X" trait to a minimal amount, and places the somewhat tricky and fragile SFINAE code away from day-to-day work.
I use C++1z's void_t.  Implementing it yourself is easy (at the bottom of this answer).
A metafunction similar to can_apply is being proposed for standardization in C++1z, but it isn't as stable as void_t is, so I'm not using it.
First, a details namespace to hide the implementation of can_apply from being found by accident:
namespace details {
  template<template<class...>class Z, class, class...>
  struct can_apply:std::false_type{};
  template<template<class...>class Z, class...Ts>
  struct can_apply<Z, std::void_t<Z<Ts...>>, Ts...>:
    std::true_type{};
}
We can then write can_apply in terms of details::can_apply, and it has a nicer interface (it doesn't require the extra void being passed):
template<template<class...>class Z, class...Ts>
using can_apply=details::can_apply<Z, void, Ts...>;
The above is generic helper metaprogramming code.  Once we have it in place, we can write a can_to_string traits class very cleanly:
template<class T>
using to_string_t = decltype( std::to_string( std::declval<T>() ) );
template<class T>
using can_to_string = can_apply< to_string_t, T >;
and we have a trait can_to_string<T> that is true iff we can to_string a T.
The work require to write a new trait like that is now 2-4 lines of simple code -- just make a decltype using alias, and then do a can_apply test on it.
Once we have that, we use tag dispatching to the proper implementation:
template<typename T>
std::string stringify(T t, std::true_type /*can to string*/){
  return std::to_string(t);
}
template<typename T>
std::string stringify(T t, std::false_type /*cannot to string*/){
  return static_cast<ostringstream&>(ostringstream() << t).str();
}
template<typename T>
std::string stringify(T t){
  return stringify(t, can_to_string<T>{});
}
All of the ugly code is hiding in the details namespace.
If you need a void_t, use this:
template<class...>struct voider{using type=void;};
template<class...Ts>using void_t=typename voider<Ts...>::type;
which works in most major C++11 compilers.
Note that the simpler template<class...>using void_t=void; fails to work in some older C++11 compilers (there was an ambiguity in the standard).
Freshly voted into the library fundamentals TS at last week's committee meeting:
template<class T>
using to_string_t = decltype(std::to_string(std::declval<T>()));
template<class T>
using has_to_string = std::experimental::is_detected<to_string_t, T>;
Then tag dispatch and/or SFINAE on has_to_string to your heart's content.
You can consult the current working draft of the TS on how is_detected and friends can be implemented. It's rather similar to can_apply in @Yakk's answer.
You could write a helper trait for this using expression SFINAE:
namespace detail
{
    //base case, to_string is invalid
    template <typename T>
    auto has_to_string_helper (...) //... to disambiguate call
       -> false_type;
    //true case, to_string valid for T
    template <typename T>
    auto has_to_string_helper (int) //int to disambiguate call
       -> decltype(std::to_string(std::declval<T>()), true_type{});
}
//alias to make it nice to use
template <typename T>
using has_to_string = decltype(detail::has_to_string_helper<T>(0));
Then use std::enable_if_t<has_to_string<T>::value>
Demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With