std::istream_iterator<> with copy_n() and friends - c++

The snippet below reads three integers from std::cin; it writes two into numbers and discards the third:
std::vector<int> numbers(2);
copy_n(std::istream_iterator<int>(std::cin), 2, numbers.begin());
I'd expect the code to read exactly two integers from std::cin, but it turns out this is a correct, standard-conforming behaviour. Is this an oversight in the standard? What is the rationale for this behaviour?
From 24.5.1/1 in the C++03 standard:
After it is constructed, and every
time ++ is used, the iterator reads
and stores a value of T.
So in the code above at the point of call the stream iterator already reads one integer. From that point onward every read by the iterator in the algorithm is a read-ahead, yielding the value cached from the previous read.
The latest draft of the next standard, n3225, doesn't seem to bear any change here (24.6.1/1).
On a related note, 24.5.1.1/2 of the current standard in reference to the istream_iterator(istream_type& s) constructor reads
Effects: Initializes in_stream with
s. value may be initialized during
construction or the first time it is
referenced.
With emphasis on "value may be initialized ..." as opposed to "shall be initialized". This sounds contradicting with 24.5.1/1, but maybe that deserves a question of its own.

Unfortunately the implementer of copy_n has failed to account for the read ahead in the copy loop. The Visual C++ implementation works as you expect on both stringstream and std::cin. I also checked the case from the original example where the istream_iterator is constructed in line.
Here is the key piece of code from the STL implementation.
template<class _InIt,
class _Diff,
class _OutIt> inline
_OutIt _Copy_n(_InIt _First, _Diff _Count,
_OutIt _Dest, input_iterator_tag)
{ // copy [_First, _First + _Count) to [_Dest, ...), arbitrary input
*_Dest = *_First; // 0 < _Count has been guaranteed
while (0 < --_Count)
*++_Dest = *++_First;
return (++_Dest);
}
Here is the test code
#include <iostream>
#include <istream>
#include <sstream>
#include <vector>
#include <iterator>
int _tmain(int argc, _TCHAR* argv[])
{
std::stringstream ss;
ss << 1 << ' ' << 2 << ' ' << 3 << ' ' << 4 << std::endl;
ss.seekg(0);
std::vector<int> numbers(2);
std::istream_iterator<int> ii(ss);
std::cout << *ii << std::endl; // shows that read ahead happened.
std::copy_n(ii, 2, numbers.begin());
int i = 0;
ss >> i;
std::cout << numbers[0] << ' ' << numbers[1] << ' ' << i << std::endl;
std::istream_iterator<int> ii2(std::cin);
std::cout << *ii2 << std::endl; // shows that read ahead happened.
std::copy_n(ii2, 2, numbers.begin());
std::cin >> i;
std::cout << numbers[0] << ' ' << numbers[1] << ' ' << i << std::endl;
return 0;
}
/* Output
1
1 2 3
4 5 6
4
4 5 6
*/

Today I encountered very similar problem, and here is the example:
#include <iostream>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <string>
struct A
{
float a[3];
unsigned short int b[6];
};
void ParseLine( const std::string & line, A & a )
{
std::stringstream ss( line );
std::copy_n( std::istream_iterator<float>( ss ), 3, a.a );
std::copy_n( std::istream_iterator<unsigned short int>( ss ), 6, a.b );
}
void PrintValues( const A & a )
{
for ( int i =0;i<3;++i)
{
std::cout<<a.a[i]<<std::endl;
}
for ( int i =0;i<6;++i)
{
std::cout<<a.b[i]<<std::endl;
}
}
int main()
{
A a;
const std::string line( "1.1 2.2 3.3 8 7 6 3 2 1" );
ParseLine( line, a );
PrintValues( a );
}
Compiling the above example with g++ 4.6.3 produces one:
1.1 2.2 3.3 7 6 3 2 1 1
, and compiling with g++ 4.7.2 produces another result :
1.1 2.2 3.3 8 7 6 3 2 1
The c++11 standard tells this about copy_n :
template<class InputIterator, class Size, class OutputIterator>
OutputIterator copy_n(InputIterator first, Size n, OutputIterator result);
Effects: For each non-negative integer i < n, performs *(result + i) = *(first + i).
Returns: result + n.
Complexity: Exactly n assignments.
As you can see, it is not specified what exactly happens with the iterators, which means it is implementation dependent.
My opinion is that your example should not read the 3rd value, which means this is a small flaw in the standard that they haven't specified the behavior.

I don't know the exact rationale, but as the iterator also has to support operator*(), it will have to cache the values it reads. Allowing the iterator to cache the first value at construction simplifies this. It also helps in detecting end-of-stream when the stream is initially empty.
Perhaps your use case is one the committee didn't consider?

Today, 9 years after you, I fell into the same problem, So following this thread, while playing with the problem noticed this, It seems we can walk the iterator one step for each reading after first time(I mean cin also can't ignore end of line feed automatically, we help it with cin.ignore(), we can help this implementation too I guess):
#include<bits/stdc++.h>
using namespace std;
int main(){
freopen("input.txt","r",stdin);
istream_iterator<int> it(cin);
ostream_iterator<int> cout_it(cout, " ");
copy_n(it, 5, cout_it);
cout<<"\nAnd for the rest of the stream\n";
for(int i=0;i<10;i++){
it++;
copy_n(it, 1, cout_it);
}
return 0;
}
and that should produce output like:
1 2 3 4 5
And for the rest of the stream
6 7 8 9 10 11 12 13 14 15

Related

why std::move behaves like std::copy? [duplicate]

This question already has answers here:
Are std::move and std::copy identical?
(2 answers)
Closed 6 years ago.
Consider the following piece of code -
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> d {100, 200, 300};
std::vector<int> l {1, 2, 3, 4, 5};
std::move(d.begin(), d.end(), std::inserter(l, l.begin()));
for (int n : l) std::cout << n << ' ';
std::cout << '\n';
for (int n : d) std::cout << n << ' ';
std::cout << '\n\n';
for (int &n : d) n +=5;
for (int n : l) std::cout << n << ' ';
std::cout << '\n';
for (int n : d) std::cout << n << ' ';
std::cout << '\n';
}
Here the original std::vector l was inserted with contents of std::vector d after the move operation. I know that all standard library objects that have been moved from are placed in a valid but unspecified state, however, I was curious to move further and inspect the values. The value of std::vector d still remained same after the move operation which could be justified as if both are referring to same data location? Again, when I tried to modify those values, the change is not reflected back in the new std::vector l container.
Here's the output -
100 200 300 1 2 3 4 5
100 200 300
100 200 300 1 2 3 4 5
105 205 305
It seems the values are copied from source container to destination container and the source container gets to keep originals. Doesn't this sound like a std::copy operation?
For plain old data, moving and copying are identical. There's no way to move ordinary data other than by copying. Things are different if, for example, you have ownership of some other object that can be transferred without copying it (like std::string or std::shared_ptr has). But for int, that doesn't apply.

Getting unexpected result when compiling with clang optimization

I found a bug in my code that only happens when I enable compiler optimizations -O1 or greater. I traced the bug and it seems that I can't use the boost type_erased adaptor on a boost transformed range when optimizations are enabled. I wrote this c++ program to reproduce it:
#include <iostream>
#include <vector>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/adaptor/type_erased.hpp>
using namespace boost::adaptors;
using namespace std;
int addOne(int b) {
return b + 1;
}
int main(int, char**) {
vector<int> nums{ 1, 2, 3 };
auto result1 = nums | transformed(addOne) | type_erased<int, boost::forward_traversal_tag>();
auto result2 = nums | transformed(addOne);
auto result3 = nums | type_erased<int, boost::forward_traversal_tag>();
for (auto n : result1)
cout << n << " ";
cout << endl;
for (auto n : result2)
cout << n << " ";
cout << endl;
for (auto n : result3)
cout << n << " ";
cout << endl;
}
When I run this program without any optimizations, I get the following output:
2 3 4
2 3 4
1 2 3
When I run it with the -O1 flag, I get the following:
1 1 1
2 3 4
1 2 3
I am using clang++ to compile it. The version of clang that I am using is:
Apple LLVM version 8.0.0 (clang-800.0.38)
I don't know if I am doing something wrong, or if it is a boost/clang bug.
edit:
Changed it to
type_erased<int, boost::forward_traversal_tag, const int>()
and it works now. The third template argument is the reference type, setting the reference to const prolongs the timespan of the temporary created by the transformed.
EDIT In fact there's more to this than meets the eye. There is another usability issue, which does address the problem. See OP's self-answer
You're falling into the number 1 pitfall with Boost Range v2 (and Boost Proto etc.).
nums | transformed(addOne) is a temporary. The type_erased adaptor stores a reference to that.
After assigning the type-erased adaptor to the resultN variable, the temporary is destructed.
What you have is a dangling reference :(
This is a highly unintuitive effect, and the number 1 reason why I limit the use of Range V2 in my codebase: I've been there all too often.
Here is a workaround:
auto tmp = nums | transformed(addOne);
auto result = tmp | type_erased<int, boost::forward_traversal_tag>();
-fsanitize=address,undefined confirms that the UB is gone when using the named temporary.
Using
type_erased<int, boost::forward_traversal_tag, const int>()
works. The third template argument is the reference type, setting the reference to const prolongs the timespan of the temporary created by the transformed.

Standard Input Iterator Issues

This is my code for solving one of the hackerrank question. In short, i am reading input for each test, solving and outputing it. For some reason, it is not reading the value of m correctly in the second iteration of the for loop based on t
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
#include <numeric>
#include <unordered_map>
using namespace std;
int main() {
bool debug = true;
istream_iterator<int> iit(cin);
int tests = *(iit++);
for (int t = 0; t < tests; t++) {
int m = *(iit++);
int n = *(iit++);
vector<int> ele; ele.reserve(n);
copy_n(iit, n, back_inserter(ele));
if (debug) {
cout << "M: " << m << ", N: " << n << ", Elements: ";
copy(ele.begin(), ele.end(), ostream_iterator<int> (cout, " "));
cout << endl;
}
unordered_map<int, int> map;
for (int index = 0; index < n; index++) {
map[ele[index]] = index;
}
bool found = false;
for (int index = 0; index < n; index++) {
auto robber = m - ele[index];
auto search_iterator = map.find(robber);
if (search_iterator != map.end()) {
int I = index + 1;
int J = search_iterator->second + 1;
cout << I << " " << J << endl;
found = true;
break;
}
}
if (debug && !found) {
cout << "Not found" << endl;
}
}
return 0;
}
And here is the input and output
04:47:20 vagrant#vm ~/cpp/icecream_parlor $ cat input.txt
2
4
5
1 4 5 3 2
4
4
2 2 4 3
04:52:49 vagrant#vm ~/cpp/icecream_parlor $ g++-4.9 -std=c++14 main.cpp -o app && ./app < input.txt
M: 4, N: 5, Elements: 1 4 5 3 2
1 4
M: 1, N: 4, Elements: 4 2 2 4
Not found
04:52:51 vagrant#vm ~/cpp/icecream_parlor $
Unlike normal iterators, stream iterators behave slightly differently.
A stream iterator is bound to some I/O stream and a copy of the iterator is still bound to the same stream.
So it violates pure value semantics, similar to how a smart pointer works, but that violation is not very obvious since it has an iterator interface.
When you call copy_n, you passed the iterator iit by value, and when the function exits, iit has not changed its internal bookkeeping state, but the underlying stream cin has got mutated because when copy_n incremented its copy of the iterator, the stream seeked forward internally.
This gotcha is a consequence of violating the contract that iterators do not change the container they point to when you read from them or increment them.
I've used stream iterators many times, I never came across this quirk, because I've never reused a stream iterator after calling copy() on it.
I think one has to just remember that this can happen and try never to reuse stream iterators after passing them to a library function.
I cannot think of a way to solve this in the language without breaking existing code that works with stream iterators.

Why std::make_move_iterator works on vector<string> but not on vector<int>

I was expecting that std::make_move_iterator will always move contents, but it seems not.
It looks like it is moving elements in vector<string> but not in vector<int>.
See the below code snippet:
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
void moveIntVector()
{
std::cout << __func__ << std::endl;
std::vector<int> v1;
for (unsigned i = 0; i < 10; ++i) {
v1.push_back(i);
}
std::vector<int> v2(
std::make_move_iterator(v1.begin() + 5),
std::make_move_iterator(v1.end()));
std::cout << "v1 is: ";
for (auto i : v1) {
std::cout << i << " ";
}
std::cout << std::endl;
std::cout << "v2 is: ";
for (auto i : v2) {
std::cout << i << " ";
}
std::cout << std::endl;
}
void moveStringVector()
{
std::cout << __func__ << std::endl;
std::vector<std::string> v1;
for (unsigned i = 0; i < 10; ++i) {
v1.push_back(std::to_string(i));
}
std::vector<std::string> v2(
std::make_move_iterator(v1.begin() + 5),
std::make_move_iterator(v1.end()));
std::cout << "v1 is: ";
for (auto i : v1) {
std::cout << i << " ";
}
std::cout << std::endl;
std::cout << "v2 is: ";
for (auto i : v2) {
std::cout << i << " ";
}
std::cout << std::endl;
}
int main()
{
moveIntVector();
moveStringVector();
return 0;
}
The result is:
moveIntVector
v1 is: 0 1 2 3 4 5 6 7 8 9 # I expect this should be `0 1 2 3 4` as well!
v2 is: 5 6 7 8 9
moveStringVector
v1 is: 0 1 2 3 4
v2 is: 5 6 7 8 9
I'm on Ubuntu 14.04, gcc 4.8.2 and the code is compiled with -std=c++11
Could you explain why std::make_move_iterator have different behaviour on vector<int> and vector<string>? (Or is it a bug?)
The behaviour is expected. A move from both vectors leaves the original v1 with 5 moved-from elements in their second half.
The difference is that when the strings are moved, what is left behind is empty strings. This is because it is a very efficient way to move strings, and leave the moved-from string in a self-consistent state (Technically, they could be left to hold the value "Hello, World, nice move!", but that would incur extra cost). The bottom line is that you don't see those moved-from strings in your output.
In the case of the int vectors, there is no way to move an int that is more efficient than copying it, so they are just copied over.
If you check the sizes of the vectors, you will see the v1 have size 10 in both cases.
Here's a simplified example to illustrate that the moved from strings are left empty:
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
int main()
{
std::vector<std::string> v1{"a", "b", "c", "d", "e"};
std::vector<std::string> v2(std::make_move_iterator(v1.begin()),
std::make_move_iterator(v1.end()));
std::cout << "v1 size " << v1.size() << '\n';
std::cout << "v1: ";
for (const auto& s : v1) std::cout << s << " - ";
std::cout << '\n';
std::cout << "v2 size " << v2.size() << '\n';
std::cout << "v2: ";
for (const auto& s : v2) std::cout << s << " - ";
std::cout << '\n';
}
Output:
v1 size 5
v1: - - - - -
v2 size 5
v2: a - b - c - d - e -
When we talk about a move we are not talking about moving the object itself (it remains intact). What gets moved are its internal data. This may or may not affect the value of the object whose internal data gets moved.
That is why your int array doesn't loose its original ints. As to your string example, it still has the original std::strings just like the int example but their internal values have changed to empty strings.
It is important to remember that internally a std::string (essentially) holds a pointer to a character array. So when you copy a std::string you copy every element of the character array. A move, however, avoids doing all that copying by copying the internal pointer instead.
But if the move operation stopped there that would leave both std::strings pointing at the same character array and changing the character data pointed to by either std::string would also change the other's. So when you move a string it is not enough to merely copy the internal pointer, you have to make the internal pointer of the std::string you moved from point to a new blank character array so that it can no longer affect the string its data was moved to.
When moving an int there is no further action required after the copy of its data. There are no pointers involved so after the copy both ints contain independent data.
move constructor is like of an object works like taking a regular reference and a instruction to move things. the default move constructor tries to call the move constructor of all member variables. a user defined one... pretty much it's up to the programmer to tell it what to do.
you could program your objects to be in a undefined state after being subject to a move constructor, you can keep them unchanged(the destructor will still be called so you need to take care of that), you can keep them valid. strings will have a defined state after being subject to a move constructor.
as for your example...
int is trivially copyable and it's move constructor won't do anything but copying.
string is not trivially copyable. it has some dynamic stuff in it that the move constructor moves. and the previous one is left with a length of zero, you ARE printing them, along with the trailing "space" which you added. it's just they are the last 5 elements, at the end of what your printing and you aren't noticing it because it's equivalent to 5 trailing white spaces.

c++ descending order with respect to second column

Text file where the data is as follows:
0 320.77
1 100.44
2 117.66
3 541.55
The data is sorted with respect to the first column but I want to sort it with respect to the second column and in descending order.
The output should be as follows:
3 541.55
0 320.77
2 117.66
1 100.44
I had a similar problem to sorting a file by the second data type, i would give code but this seems to be a homework problem, so here is an explanation of how i solved it:
read the line into a string
iterate to the second number by skipping to the next space
grab the second number from the string and place it in a separate string, then atoi() the string to get an integer
sort the string using the integer in a sort function then call the function in std::sort of qsort()
I think that would not hurt #laky college performance now if I entertain myself a bit and provide an answer.
#include <utility>
#include <sstream>
#include <vector>
#include <iostream>
#include <algorithm>
using Entry = std::pair<int, float>;
using Storage = std::vector<Entry>;
void dump(const Storage& storage)
{
for(auto& [i, v] : storage)
std::cout << i << " " << v << "\n";
}
int main(void)
{
std::stringstream input;
input.str("0 320.77\n1 100.44\n2 117.66\n3 541.55\n");
Storage storage;
for ( /* read 'file' into vector storage for processing */
Entry entry;
input >> entry.first >> entry.second && input.good();
)
{
storage.push_back(std::move(entry));
}
std::cout << "Original data:\n";
dump(storage);
std::sort(storage.begin(), storage.end(),
[](Entry l, Entry r) /* sorting predicate */
{
return l.second > r.second;
});
std::cout << "Sorted data:\n";
dump(storage);
return 0;
}
on GodBolt