2014-11-07 3 views
11

Если я правильно понял правила для времени жизни временных рядов, этот код должен быть безопасным, так как время жизни временного stringstream в make_string() длится до конца полного выражения. Я не уверен на 100%, но здесь нет тонкой проблемы, может ли кто-нибудь подтвердить, безопасен ли этот шаблон использования? Кажется, что он отлично работает в clang и gcc.C++ время жизни времен - это безопасно?

#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"); 
} 
+3

Мне кажется, все должно быть хорошо. –

+0

Технически это нормально, но я считаю, что вы обнаружите, что это довольно неэффективно. Рассмотрим просто определение построителя строк с помощью 'operator <<'. –

+0

@ Cheersandhth.-Alf Зависит от того, насколько агрессивно работает компилятор. – cdhowie

ответ

7

Соответствующая часть стандарта в §12.2:

12.2.3) Временные объекты уничтожаются на последнем этапе при оценке полного выражения (1.9) следует, что (лексический) содержит где они были созданы.

За исключением:

12.2.4) Есть два контекста, в котором уничтожаются временные конструкции в другом месте, чем в конце полного выражения. Первый контекст - это когда вызывается конструктор по умолчанию для инициализации элемента массива. ... [не применяется]

12.2.5) Второй контекст - это когда ссылка привязана к временному. Временный, к которому ссылка привязана или временное, что является полным объектом подобъекту, к которому ссылка привязана сохраняется в течение всего срока ссылки, за исключением:

  • ...

  • временная привязка к эталонному параметру в вызове функции (5.2.2) сохраняется до завершения полного выражения, содержащего вызов.

Так что вы идете. Временной stringstream{} привязан к ссылке в вызове функции, поэтому он сохраняется до завершения выражения. Это безопасно.

+0

Спасибо, это выглядит довольно однозначно :) – mattnewport

Смежные вопросы