Nemanja
Nemanja

Reputation: 154

Restrict function template to specific types?

I want to make function that will make easy to concatenate string. Let suppose I have struct A:

struct A {
    int a;
    double b;
}

Now i want to print like this:

A a = {1, 2.0};
cout << someString + string{"dsdassa"} + a;

or to concat string like this:

string s{"das"};
string s2 = s + A{1, 2.0f};

So i make function like this:

template <typename T>
std::string operator+(std::string & lhs, T && t)
{
    std::cout<< std::endl << "LOG" << '\t' << "operator+(std::string & lhs, T && t)" << std::endl;

    std::string neww(lhs);
    neww += ' ';
    neww += std::to_string(t);
    return neww;
}

For this function to work type T have to have std::to_string function specialized.

If I implement std::to_string for A like this:

 namespace std {
     std::string to_string(A & a)
     {
         return "a = " + std::toString(a.a) + ", b= " + std::to_string(a.b);
     }
 }

examples above will work.

Problem with this is that this will not work if I try to concat 2 strings like this: cout << s + std::string{"blabla"}; because there is no std::to_string for std::string;

I think this could be solved if I somehow could restrict operator+ function to types that have std::to_string.

Is it possible?

Upvotes: 1

Views: 576

Answers (1)

alfC
alfC

Reputation: 16242

The typical answer these days is this. To define the function with an extra template parameter that will make the function be ignored if the dummy type constructed from the expression doesn't exist.

template <typename T, typename = decltype(std::to_string(std::declval<T>()))>
std::string operator+(std::string & lhs, T && t)
{
...
}

It can be more refined by it does what you want.

Another more elegant syntax is this

template <typename T>
auto operator+(std::string & lhs, T && t) -> decltype(std::to_string(t)) 
{
...
}

This exploits a language feature called SFINAE.

Upvotes: 3

Related Questions