N2976 suggested adding constexpr
to some spots in the standard library. It notes that iostream
s are inappropriate for constexpr
EXCEPT end iterators. So istream_iterator
and istreambuf_iterator
were given constexpr
default constructors and that's about it. For example, you can see in the libstdc++ implementation that constexpr
only appears once in the entire file. The LWG that sparked this change was #1129. It says:
istream_iterator
andistreambuf_iterator
should support literal sentinel values. The default constructor is frequently used to terminate ranges, and could easily be a literal value foristreambuf_iterator
, andistream_iterator
when iterating value types. [Rest omitted]
This doesn't make a whole lot of sense to me. Can someone show me an example of what they mean?
N3308 is another paper that mentions but doesn't explain the issue:
Some of the
istream_iterator<T>
constructors are required to beconstexpr
ifT
is a literal type. The intention is to allow existing implementation technique of storing a type ofT
inline to continue to work. [libstdc++ does this,_Tp _M_value
] However, it actually rules out this technique: the default and copy constructors ofT
need not be markedconstexpr
, and if they are not, theistream_iterator<T>
constructors could not be instantiated asconstexpr
.
The above explains the trivial copy constructor and destructor, but not why the default constructor is marked constexpr.
Furthermore, testing on online GCC 5.2.0, I copied libstdc++'s implementation. The only change is I removed constexpr from istream_iterator()
. In both cases, the assemblies are identical.
With constexpr
Without constexpr
An example of an-end of stream iterator being used as a sentinel value is here:
// 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/
Declaring this a constexpr
allows the compiler to fold calls that create end-of-stream iterators into constants, rather than calling a function each time. It might otherwise have to do so on each iteration of a loop.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With