将函数模板限制为特定类型?

Restrict function template to specific types?

我想制作一个可以轻松连接字符串的函数。 假设我有 struct A:

struct A {
    int a;
    double b;
}

现在我想这样打印:

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

或者像这样连接字符串:

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

所以我做了这样的功能:

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;
}

要使此函数工作,类型 T 必须具有 std::to_string 函数专用。

如果我像这样为 A 实现 std::to_string

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

以上示例都可以。

问题在于,如果我尝试像这样连接 2 个字符串,这将不起作用:cout << s + std::string{"blabla"}; 因为 std::string 没有 std::to_string

我认为如果我能以某种方式将 operator+ 函数限制为具有 std::to_string.

的类型,我认为这可以解决

可能吗?

最近的典型答案是这样的。使用额外的模板参数定义函数,如果从表达式构造的虚拟类型不存在,该函数将被忽略。

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

它可以做你想做的更精致。

另一个更优雅的语法是

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

这利用了称为 SFINAE 的语言功能。