我怎样才能优化这个简单的功能?

时间:2014-07-03 02:26:03

标签: c++ templates c++11

假设我有以下内容:

template <class T>
std::string to_string(const T& item)
{
    std::ostringstream ss;
    ss << item;
    return ss.str();
}

是否有可能创建to_string的重载,在给定std::string的情况下,只需转发参数而没有任何开销?

4 个答案:

答案 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

Live demo


您也可以std::to_string通过T使用std::is_arithmetic<T>将代码发送到std::to_stringtemplate <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);

Live demo


最后,如果您可以使用提升功能,则可以使用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;将调用一般函数而不是专用函数。

我希望这会解决您的问题。