【发布时间】:2014-11-07 03:00:40
【问题描述】:
如果我正确理解了临时对象的生命周期规则,那么这段代码应该是安全的,因为 make_string() 中的临时 stringstream 的生命周期一直持续到完整表达式的末尾。我不是 100% 确信这里没有一个微妙的问题,有人可以确认这种使用模式是否安全吗?它似乎在 clang 和 gcc 中运行良好。
#include <iomanip>
#include <iostream>
#include <sstream>
using namespace std;
ostringstream& make_string_impl(ostringstream&& s) { return s; }
template<typename T, typename... Ts>
ostringstream& make_string_impl(ostringstream&& s, T&& t, Ts&&... ts) {
s << t;
return make_string_impl(std::move(s), std::forward<Ts>(ts)...);
}
template<typename... Ts>
string make_string(Ts&&... ts) {
return make_string_impl(ostringstream{}, std::forward<Ts>(ts)...).str();
}
int main() {
cout << make_string("Hello, ", 5, " World!", '\n', 10.0, "\n0x", hex, 15, "\n");
}
【问题讨论】:
-
在我看来应该没问题。
-
技术上没问题,但我相信你会发现它相当低效。考虑使用
operator<<定义一个字符串构建器。 -
@Cheersandhth.-Alf 取决于编译器内联的积极程度。
-
@cdhowie:不,我在想
stringstream。应该是ostringstream,但这无济于事。问题是它对语言环境的支持非常普遍,所以,它通常很慢。 -
这可行,但为了便于阅读,我倾向于在
make_string()中使用以下内容:ostringstream s; make_string_impl(s, ts...); return s.str();。它没有那么聪明,但它可以让你在make_string_impl()中使用ostringstream&,这意味着你可以省略std::move()的讨厌——只是传递一个引用。然后make_string_impl()也可以返回void。更容易阅读,更容易让编译器内联。它还回避了您对该技术安全性的疑问。