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

Restrict function template to specific types?

本文关键字:类型 函数模板      更新时间:2023-10-16

我想制作一个函数,使字符串连接变得容易。假设我有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);
     }
 }

上面的例子会起作用。

问题是,如果我尝试像这样连接两个字符串,这将不起作用: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的语言功能。