将功能模板限制为特定类型?

时间:2016-01-06 09:17:38

标签: c++ templates c++11 sfinae

我想创建一个易于连接字符串的函数。 假设我有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功能专用。

如果我为std::to_string实施A,请执行以下操作:

 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::to_string没有std::string;

我认为如果我以某种方式将operator+函数限制为具有std::to_string的类型,就可以解决这个问题。

有可能吗?

1 个答案:

答案 0 :(得分:3)

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

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的语言功能。