I have template code which needs to convert some template type to string. For this I overload to_string for my own types. But the type can also be a string already. Then compilation fails, because there is no overload of to_string for type string itself (just returning its argument).
edit: example code:
template<class T>
class TemplatedClass
{
public:
string toString() const
{
    // this should work for both simple types like int, double, ...
    // and for my own classes which have a to_string overload
    // and also for string, which is the reason for my question
    return string("TemplatedClass: ").append(to_string(t_));
}
private:
    T t_;
};
                You can just write your own templated function with proper overloads as follows:
#include <iostream>
#include <string>
using namespace std;
template<typename T>
std::string toString(const T& t) {
    return std::to_string(t);
}
std::string toString(const char* t) {
    return t;
}
std::string toString(const std::string& t) {
    return t;
}
int main() {
    cout << toString(10) << endl;
    cout << toString(1.5) << endl;
    cout << toString("char*") << endl;
    cout << toString(std::string("string")) << endl;
    return 0;
}
                        You can just combine all std::to_string and all your to_string by using derective. And pass std::string by value to minimize number of copies:
#include <string>
#include <iostream>
namespace convert {
    std::string to_string(std::string s)
    {
        return s;
    }
    template<class T>
    std::string stringify(T&& t)
    {
        using convert::to_string;
        using std::to_string;
        return to_string(std::forward<T>(t));
    }
}
class Foo
{
public:
    operator std::string () const { return "Foo"; }
};
namespace bar {
    class Bar
    {};
    std::string to_string(const Bar&) {
        return "Bar";
    }
}
int main()
{
    std::string s{"I'm lvalue string"};
    std::cout << convert::stringify(42) << "\n";
    std::cout << convert::stringify(std::string("I'm string")) << "\n";
    std::cout << convert::stringify("I'm c-string") << "\n";
    std::cout << convert::stringify(s) << "\n";
    std::cout << convert::stringify(Foo{}) << "\n";
    std::cout << convert::stringify(bar::Bar{}) << "\n";
    return 0;
}
Note that with my approach you don't need an overload for const char * or any other type that is convertible to a string. Also this approach allows a user to add to_string overload for any class (it will be found by argument-dependent lookup).
For further optimization convert::to_string accepting a string by value can be split into lvalue and rvalue overloads.
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