将函数模板限制为特定类型?
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 的语言功能。
我想制作一个可以轻松连接字符串的函数。
假设我有 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 的语言功能。