假设我有以下内容:
template <class T>
std::string to_string(const T& item)
{
std::ostringstream ss;
ss << item;
return ss.str();
}
是否有可能创建to_string
的重载,在给定std::string
的情况下,只需转发参数而没有任何开销?
答案 0 :(得分:6)
我添加了一些重载,一个返回左值std::string
的副本,另一个重载move
是右值std::string
。
std::string to_string(const std::string& item)
{
return item;
}
std::string to_string(std::string&& item)
{
return std::move(item);
}
std::string s("Hello, World!");
std::cout << to_string(s) << std::endl; // calls the lvalue overload
std::cout << to_string(std::string("Hello, World!")) << std::endl; // calls the rvalue overload
std::cout << to_string(20) << std::endl; // calls the function template
您也可以std::to_string
通过T
使用std::is_arithmetic<T>
将代码发送到std::to_string
来template <class T>
std::string to_string_impl(const T& item, std::true_type)
{
return std::to_string(item);
}
template <class T>
std::string to_string_impl(const T& item, std::false_type)
{
std::ostringstream ss;
ss << item;
return ss.str();
}
template <class T>
std::string to_string(const T& item)
{
return to_string_impl(item, std::is_arithmetic<T>{});
}
数字来完成工作。
auto str = boost::lexical_cast<std::string>(whatever);
最后,如果您可以使用提升功能,则可以使用boost::lexical_cast
替换您的功能。
{{1}}
答案 1 :(得分:5)
是否可以创建
to_string
的重载,如果给出std::string
...
当然。
std::string to_string(const std::string& str) {
return str;
}
...只是简单地转发参数而没有任何开销?
不确定你的意思&#34;转发&#34;在这里,但是......
如果提供临时或std::move
d对象作为to_string
的参数,则可以提供另一个重载。使用r值参考。
std::string to_string(std::string&& str) {
return std::move(str);
}
请注意,返回语句中的std::move
在此处是必需的,因为如果未使用它将导致副本(编译器将所有命名变量视为左值,并使用str
命名变量,需要std::move
)。
现在你为std::string
重载了两个版本,第一个版本将有效地返回所提供参数的副本,而第二个版本将利用临时对象和显式std::move
d个对象。
std::string str = "Hello World!";
auto str1 = to_string(str); // *effectively* copies str to str1 [1]
auto str2 = to_string("Hi"); // *effectively* moves the temporary created here [1]
auto str3 = to_string(std::move(str)); // *effectively* moves str to str3; [1]
[1]实际上,在返回时仍然会有可能几个额外的移动,并且在某些情况下编译器可以应用可以 。
<强>更新强>
不会
auto str2 = to_string("Hi");
调用模板函数,因为这不涉及隐式转换,因此更合适的重载? link
你是对的。这样,您可以提供另一个接受const char*
std::string to_string(const char* str) {
return str;
}
或者您可以记录行为并让(更像是强制)用户执行to_string(std::string("bah"))
。我很确定你会提供过载: - )。
答案 2 :(得分:0)
如果你关心表现,远离任何stringstream
流及其il,他们会非常慢。你纠正了你可以引入一个重载,例如std::string to_string( const std::string& item )
,这将是一个更好的匹配并被选中。还有boost::lexical_cast
,也许在c ++ 11中有类似的东西(其他人将不得不在这里筹码)。 boost::lexical_cast
但由于其内部依赖于stringstream
,因此也非常缓慢。 IMO最好的方法是介绍您自己的功能,例如您已完成to_string
,回退到boost::lexical_cast
并为您自己的类型专门化/重载。我们使用boost::spirit::qi
对我们的很多类型进行了专门化,那里的性能比较与我们的测试一致,它很容易使用boost::spirit::qi
及其解析器获取方式比stringstream
更好的性能特征。
答案 3 :(得分:0)
如果我已正确理解您的问题,那么您要求&#34;模板专业化&#34;。
template <class T>
std::string to_string(const T& item)
{
std::ostringstream ss;
ss << item;
return ss.str();
}
std::string to_string (const string& item)
{
return item;
}
重要提示:
在to_string函数中,我们传递了&#34; const string&amp;&#34;,因此函数调用应该是这样的:
string my_string = "ABC";
to_string (my_string);
调用专门的函数。
如果你调用to_string:
to_string ("ABC");
然后&#34; std :: string to_string(const T&amp; item)&#34;将调用一般函数而不是专用函数。
我希望这会解决您的问题。