Какой смысл использовать constexpr end istream (sentinel) итераторы?
N2976 предложил добавить constexpr
в некоторые места в стандартной библиотеке. Отмечает, что iostream
с не подходит для constexpr
ЗА ИСКЛЮЧЕНИЕМ конечных итераторов. Так istream_iterator
а также istreambuf_iterator
были даны constexpr
конструкторы по умолчанию, и это все. Например, вы можете увидеть в реализации libstdC++, что constexpr
появляется только один раз во всем файле. LWG, которая вызвала это изменение, была # 1129. Это говорит:
istream_iterator
а такжеistreambuf_iterator
должен поддерживать буквальные значения дозорного Конструктор по умолчанию часто используется для завершения диапазонов и может легко быть буквальным значением дляistreambuf_iterator
, а такжеistream_iterator
при переборе типов значений. [Остальные опущены]
Это не имеет большого смысла для меня. Может кто-нибудь показать мне пример того, что они имеют в виду?
N3308 - это еще одна статья, в которой упоминается, но не объясняется проблема:
Некоторые из
istream_iterator<T>
конструкторы должны бытьconstexpr
еслиT
это буквальный тип. Намерение состоит в том, чтобы позволить существующим методам реализации сохранять типT
встроенный, чтобы продолжить работу. [libstdC++ делает это,_Tp _M_value
Тем не менее, это фактически исключает эту технику: конструкторы по умолчанию и копированияT
не должны быть отмеченыconstexpr
и если нет, тоistream_iterator<T>
конструкторы не могут быть созданы какconstexpr
,
Вышесказанное объясняет тривиальный конструктор копирования и деструктор, но не объясняет, почему конструктор по умолчанию помечен как constexpr.
Кроме того, тестируя онлайн GCC 5.2.0, я скопировал реализацию libstdC++. Единственное изменение - я удалил constexpr из istream_iterator()
, В обоих случаях сборки идентичны.
1 ответ
Пример конца потокового итератора, используемого в качестве часового значения, приведен здесь:
// istream_iterator example
#include <iostream> // std::cin, std::cout
#include <iterator> // std::istream_iterator
int main () {
double value1, value2;
std::cout << "Please, insert two values: ";
std::istream_iterator<double> eos; // end-of-stream iterator
std::istream_iterator<double> iit (std::cin); // stdin iterator
if (iit!=eos) value1=*iit;
++iit;
if (iit!=eos) value2=*iit;
std::cout << value1 << "*" << value2 << "=" << (value1*value2) << '\n';
return 0;
}
http://www.cplusplus.com/reference/iterator/istream_iterator/istream_iterator/
Объявив это constexpr
позволяет компилятору сворачивать вызовы, которые создают итераторы конца потока в константы, вместо того, чтобы каждый раз вызывать функцию. В противном случае он мог бы делать это на каждой итерации цикла.