3

I can create an std::istringstream like so

std::istringstream string_stream(inp_string);

I can then change the contents of the stream:

string_stream.str(std::move(inp_string_2));

However, I might accidentally try something like this:

string_stream.str() = inp_string_2;

This compiles, but will not change the contents of string_stream. If you check the return value of std::istringstream::str() here, you will see that the return value is of non-reference type.

I believe that std::istringstream::str() is an r-value, and writing it on the left side of the equals sign should give an error, but the following code compiles in MSVC:

#include <iostream>
#include <string>
#include <sstream>


int main() {
    // Create string stream
    std::string inp_string = "this is a test string";
    std::istringstream string_stream(inp_string);


    // Try to replace the string stream
    std::string inp_string_2 = "a new test string";

    // incorrect:
    string_stream.str() = inp_string_2;            // Expected Error
    string_stream.str() = std::move(inp_string_2); // Expected Error

    // correct:
    // string_stream.str(std::move(inp_string_2));


    // Check contents of string stream
    std::cout << string_stream.str();
}

The output is

this is a test string

A Related Example

Below is similar example that will fail to compile:

#include <iostream>
#include <vector>


class MyClass {
private:
    std::vector<int> my_vec;

public:
    MyClass(std::vector<int>& vec) : my_vec(std::move(vec)){}

    int operator() (int i) {
        return my_vec[i];
    }
};


int main() {
    std::vector<int> inp = { 1, 2, 3, 4,  5 };
    MyClass my_class(inp);
    my_class(3) = 2;               // ERROR
    std::cout << my_class[3];

}

This gives the error

error C2106: '=': left operand must be l-value

as expected.

user589321
  • 99
  • 6
  • 1
    Fundamental and user-defined types are different in this respect. Related note: https://en.cppreference.com/w/cpp/iterator/next#Notes – Evg Mar 10 '22 at 20:13
  • 5
    The relation to `stringstream` is a red herring. A much shorter example: `#include int main() { std::string() = "Hello"; }` – WhozCraig Mar 10 '22 at 20:18
  • 1
    This compiles not only in MSVC. The alternative is returning a `const` object. Also, in C++ there are many more cases where you are allowed to write nonsensical code. – Wolf Mar 10 '22 at 20:23
  • 1
    It only recently became possible for member functions to overload based on rvalue-ness of `*this`. – Ben Voigt Mar 10 '22 at 20:28
  • 1
    The target is about assigning to a `std::string` temporary, but it's the same idea as in your question. – cigien Mar 10 '22 at 20:30
  • @cigien Thanks. My question is a duplicate of yours. However, after reading the responses, I am not satisfied by the answers. None of the answers to your question provided a single use-case. – user589321 Mar 10 '22 at 21:30
  • There *aren't* any use-cases really :) It's just that we *couldn't* restrict assignment to temporaries until C++11, and now it hasn't been considered worthwhile to add that restriction yet. – cigien Mar 11 '22 at 00:06

0 Answers0