#include <iostream>
#include <iterator>
#include <sstream>
int main()
{
const std::string s = "The quick brown fox jumps over the lazy dog.";
std::cout << "stringstream ranger:\n";
std::istringstream iss( s );
for (auto word : ranger( std::istream_iterator <std::string> ( iss ) ))
{
std::cout << " " << word << "\n";
}
std::cout << "\n""regex re_ranger:\n";
for (auto word : re_ranger( "[^\\s]+", s ))
{
std::cout << " " << word.str() << "\n";
}
}
stringstream ranger:
The
quick
brown
fox
jumps
over
the
lazy
dog.
regex re_ranger:
The
quick
brown
fox
jumps
over
the
lazy
dog.
Remember, folks, that doing this means doing an end-run around C++’s safety checks and treating a temporary object as if it were not. Don’t use it outside of contexts where the temporary is guaranteed to exist.
Example: Simple word count program. Takes input from either a list of files or from standard input.
1 2 3 4 5 6 7 8 9 10
unsigned word_count( std::istream& );
int main( int argc, char** argv )
{
unsigned sum = 0;
if (argc > 1) while (argc --> 1) sum += word_count( lvalue( std::ifstream( argv[argc] ) ) );
else sum = word_count( std::cin );
std::cout << sum << "\n";
}
The return value of std::remove_reference() can't be passed to a function expecting a T &, only a const T & or a T &&.
Another thing it might be useful for could be
lvalue(Foo(...)) = bar;
Here, Foo might open a life and the assignment might serialize bar and save it.
This is a simple function that I use for input validation, to make sure the user doesn't enter a letter when he should enter a number. It's kind of hackish, but it works. I use it because I'm a nut about this sort of thing.
The return value of std::remove_reference() can't be passed to a function expecting a T &, only a const T & or a T &&.
Right :+)
There is also std::add_lvalue_reference, std::add_rvalue_reference as well as the other stuff in traits, like const-volatility specifiers et al. So one can wrangle the type specifier any which way.
The return value of std::remove_reference() can't be passed to a function expecting a T&
remove_reference is a class template that computes a type, so it would need to be used with a conversion of some kind
Maybe something like this (tricky, and perhaps not even entirely correct) static_cast<typename std::remove_reference<decltype((expression))>::type&>(expression)
The "extra" parentheses are required around expression
Or perhaps, (even more tricky) static_cast<decltype((expression))&>(expression)
The lvalue function may be useful with iterator adapters, for example when constructing regex_token_iterator.
It can be used as long as one understands lifetime rules. For example parse(regex_token_iterator{text_begin, text_end, lvalue(std::regex{"."})}, regex_token_iterator{});
Note that declaring an extra variable is a small price to pay to eliminate avoidable and subtle lifetime bugs.
Extract unsigned integers from a byte stream with known endianness:
Up-to-date mainstream compilers understand this idiom and generate byte swap instructions if appropriate