3

The following code works on my computer, but is this guaranteed to work by the C++ standard?

void do_stuff(std::string);
std::string s;

while(std::cin >> s){
    do_stuff(std::move(s));
}

From my understanding of the standard, objects that are moved from are left in a valid but unspecified state, and are only worthy of destruction. Hence, the code isn't guaranteed to work.

As an extension, is the following valid, given the knowledge of the Notification class and the fact that get_notification overwrites the member details?

struct Notification{
    string details;
};

string get_string();
void do_more_stuff(Notification);
void get_notification(Notification& n){
    n.details = get_string();
}

Notification n;

while(get_notification(n)){
    do_more_stuff(std::move(n));
}
Steephen
  • 11,597
  • 6
  • 29
  • 41
Bernard
  • 4,001
  • 1
  • 23
  • 48
  • I think that it depends on the type. `std::string` says _Move constructor. Constructs the string with the contents of other using move semantics. other is left in valid, but unspecified state._ `basic_stream_socket::operator=` (boost asio) on the other hand says _Following the move, the moved-from object is in the same state as if constructed using the basic_stream_socket(io_service&) constructor._ , which means that you can continue to use the moved-from object in a call to e.g. `accept`. – simon Jan 25 '17 at 14:14
  • Possible duplicate of [What constitutes a valid state for a "moved from" object in C++11?](http://stackoverflow.com/questions/12095048/what-constitutes-a-valid-state-for-a-moved-from-object-in-c11) – François Andrieux Jan 25 '17 at 14:16
  • How could "valid" mean "only worthy of destruction"? – el.pescado Jan 26 '17 at 07:35

1 Answers1

4

From my understanding of the standard, objects that are moved from are left in a valid but unspecified state,

This part is true.

and are only worthy of destruction

This part is not true. There are things you can do with an object that was moved from: any operation that does not have a precondition. For instance, clear() has no preconditions on the string, so you can clear() a moved-from string. At that point, you are in a specified state. Similarly, erase() has no preconditions.

operator>> is another operation that has no preconditions (indeed, it is specified to call erase()). So this code:

while(std::cin >> s){
    do_stuff(std::move(s));
}

is actually fine.

Barry
  • 247,587
  • 26
  • 487
  • 819
  • I think you *can* perform operations with precondition (i.e. read state from object): it's not particularly useful as the outcome is unknown, but it should be guaranteed not to crash. For example, you can `std::cout << s` as well, but characters that end up on screen are not specified, it may be original string, empty string or even (U+1F4A9) 'PILE OF POO'. All of those are valid possible outcomes. – el.pescado Jan 26 '17 at 07:50
  • @el.pescado Performing operations with preconditons would be undefined behavior. It is not guaranteed not to crash. – Barry Jan 26 '17 at 13:12
  • I thought about it and I think you're right. I confused "querying state" with "having preconditions". – el.pescado Jan 26 '17 at 14:17