Search code examples
c++templatessfinae

Generic function template deduction over existing function overloads


I'm writing an extensible library where it has become convenient to overload STL's to_string() for custom types. For that I've designed a generic overload template that throws an exception if not specialized:

namespace std {
// ...
template < typename T >
inline std::string to_string(const T& in, const std::string& separator = ",") {
    throw std::runtime_error("invalid call to " + std::string(__func__) + "(): missing template specialization for type " + typeid(T).name());
}

}  // namespace std

This is useful mainly because the description will provide a clear explanation on the issue and how to solve it, and avoids having to use polymorphism to implement derived implementations (the function is only marginally/optionally required for certain applications such as serialization, I/O, etc.).

However, the issue with this approach is that the overload template will be deduced even with types where <string> already provides an overload for.

My question is if is there a way to force the non-template overload to be used only when there is no non-template definition available?


Solution

  • I recommend that you do not generate a runtime exception for something that should be a compilation failure.

    It could look like this:

    #include <string>
    #include <type_traits>
    
    namespace extra {
    template <class T>
    inline std::string to_string(const T& in) {
        static_assert(std::is_arithmetic_v<T>, "T needs extra::to_string overload");
        return std::to_string(in); 
    }
    }  // namespace extra
    

    ... and then you don't need to check if it's an arithmetic type at the call site:

    template <class T>
    void func(const T& arg) {
        std::cout << extra::to_string(arg);
    }
    

    Demo