This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++20 status.

### 3130. §[input.output] needs many `addressof`

Section: 31 [input.output] Status: C++20 Submitter: Tim Song Opened: 2018-06-30 Last modified: 2021-02-25

Priority: 0

View all other issues in [input.output].

View all issues with C++20 status.

Discussion:

There are 27 instances of `&sb` and one instance of `&rhs` in Clause 31 [input.output], each of which needs to use `addressof` because the operand has a user-provided template type parameter as an associated class and so the use of unary `&` is subject to ADL hijacking.

[2018-07-20 Status to Tentatively Ready after five positive votes on the reflector.]

[2018-11, Adopted in San Diego]

Proposed resolution:

This wording is relative to N4750.

1. Change 31.5.4.3 [basic.ios.members] p16 as indicated:

   >     basic_ios& copyfmt(const basic_ios& rhs);

   > > -16- Effects: If `(this == &addressof(rhs))` does nothing. […]

2. Change 31.8.3.2 [istringstream.cons] as indicated:

   >     explicit basic_istringstream(ios_base::openmode which);

   > > -1- Effects: Constructs an object of class `basic_istringstream<charT, traits>`, initializing the base class with `basic_istream<charT, traits>(&addressof(sb))` (31.7.5.2 [istream]) and initializing `sb` with `basic_stringbuf<charT, traits, Allocator>(which | ios_base::in)` (31.8.2.2 [stringbuf.cons]).

   >     explicit basic_istringstream(
   >       const basic_string<charT, traits, Allocator>& str,
   >       ios_base::openmode which = ios_base::in);

   > > -2- Effects: Constructs an object of class `basic_istringstream<charT, traits>`, initializing the base class with `basic_istream<charT, traits>(&addressof(sb))` (31.7.5.2 [istream]) and initializing `sb` with `basic_stringbuf<charT, traits, Allocator>(str, which | ios_base::in)` (31.8.2.2 [stringbuf.cons]).

   >     basic_istringstream(basic_istringstream&& rhs);

   > > -3- Effects: Move constructs from the rvalue `rhs`. This is accomplished by move constructing the base class, and the contained `basic_stringbuf`. Next `basic_istream<charT, traits>::set_rdbuf(&addressof(sb))` is called to install the contained `basic_stringbuf`.

3. Change 31.8.3.4 [istringstream.members] p1 as indicated:

   >     basic_stringbuf<charT, traits, Allocator>* rdbuf() const;

   > > -1- Returns: `const_cast<basic_stringbuf<charT, traits, Allocator>*>(&addressof(sb))`.

4. Change 31.8.4.2 [ostringstream.cons] as indicated:

   >     explicit basic_ostringstream(ios_base::openmode which);

   > > -1- Effects: Constructs an object of class `basic_ostringstream<charT, traits>`, initializing the base class with `basic_ostream<charT, traits>(&addressof(sb))` (31.7.6.2 [ostream]) and initializing `sb` with `basic_stringbuf<charT, traits, Allocator>(which | ios_base::out)` (31.8.2.2 [stringbuf.cons]).

   >     explicit basic_ostringstream(
   >       const basic_string<charT, traits, Allocator>& str,
   >       ios_base::openmode which = ios_base::out);

   > > -2- Effects: Constructs an object of class `basic_ostringstream<charT, traits>`, initializing the base class with `basic_ostream<charT, traits>(&addressof(sb))` (31.7.6.2 [ostream]) and initializing `sb` with `basic_stringbuf<charT, traits, Allocator>(str, which | ios_base::out)` (31.8.2.2 [stringbuf.cons]).

   >     basic_ostringstream(basic_ostringstream&& rhs);

   > > -3- Effects: Move constructs from the rvalue `rhs`. This is accomplished by move constructing the base class, and the contained `basic_stringbuf`. Next `basic_ostream<charT, traits>::set_rdbuf(&addressof(sb))` is called to install the contained `basic_stringbuf`.

5. Change 31.8.4.4 [ostringstream.members] p1 as indicated:

   >     basic_stringbuf<charT, traits, Allocator>* rdbuf() const;

   > > -1- Returns: `const_cast<basic_stringbuf<charT, traits, Allocator>*>(&addressof(sb))`.

6. Change 31.8.5.2 [stringstream.cons] as indicated:

   >     explicit basic_stringstream(ios_base::openmode which);

   > > -1- Effects: Constructs an object of class `basic_stringstream<charT, traits>`, initializing the base class with `basic_iostream<charT, traits>(&addressof(sb))` (31.7.5.7.2 [iostream.cons]) and initializing `sb` with `basic_stringbuf<charT, traits, Allocator>(which)`.

   >     explicit basic_stringstream(
   >       const basic_string<charT, traits, Allocator>& str,
   >       ios_base::openmode which = ios_base::out | ios_base::in);

   > > -2- Effects: Constructs an object of class `basic_stringstream<charT, traits>`, initializing the base class with `basic_iostream<charT, traits>(&addressof(sb))` (31.7.5.7.2 [iostream.cons]) and initializing `sb` with `basic_stringbuf<charT, traits, Allocator>(str, which)`.

   >     basic_stringstream(basic_stringstream&& rhs);

   > > -3- Effects: Move constructs from the rvalue `rhs`. This is accomplished by move constructing the base class, and the contained `basic_stringbuf`. Next `basic_istream<charT, traits>::set_rdbuf(&addressof(sb))` is called to install the contained `basic_stringbuf`.

7. Change 31.8.5.4 [stringstream.members] p1 as indicated:

   >     basic_stringbuf<charT, traits, Allocator>* rdbuf() const;

   > > -1- Returns: `const_cast<basic_stringbuf<charT, traits, Allocator>*>(&addressof(sb))`.

8. Change 31.10.3.2 [ifstream.cons] as indicated:

   >     basic_ifstream();

   > > -1- Effects: Constructs an object of class `basic_ifstream<charT, traits>`, initializing the base class with `basic_istream<charT, traits>(&addressof(sb))` (31.7.5.2.2 [istream.cons]) and initializing `sb` with `basic_filebuf<charT, traits>()` (31.10.2.2 [filebuf.cons]).

   >     explicit basic_ifstream(const char* s,
   >                             ios_base::openmode mode = ios_base::in);
   >     explicit basic_ifstream(const filesystem::path::value_type* s,
   >                             ios_base::openmode mode = ios_base::in);  // wide systems only; see 31.10.1 [fstream.syn]

   > > -2- Effects: Constructs an object of class `basic_ifstream<charT, traits>`, initializing the base class with `basic_istream<charT, traits>(&addressof(sb))` (31.7.5.2.2 [istream.cons]) and initializing `sb` with `basic_filebuf<charT, traits>()` (31.10.2.2 [filebuf.cons]), then calls `rdbuf()->open(s, mode | ios_base::in)`. If that function returns a null pointer, calls `setstate(failbit)`.

   > […]

   >     basic_ifstream(basic_ifstream&& rhs);

   > > -4- Effects: Move constructs from the rvalue `rhs`. This is accomplished by move constructing the base class, and the contained `basic_filebuf`. Next `basic_istream<charT, traits>::set_rdbuf(&addressof(sb))` is called to install the contained `basic_filebuf`.

9. Change 31.10.3.4 [ifstream.members] p1 as indicated:

   >     basic_filebuf<charT, traits>* rdbuf() const;

   > > -1- Returns: `const_cast<basic_filebuf<charT, traits>*>(&addressof(sb))`.

10. Change 31.10.4.2 [ofstream.cons] as indicated:

    >     basic_ofstream();

    > > -1- Effects: Constructs an object of class `basic_ofstream<charT, traits>`, initializing the base class with `basic_ostream<charT, traits>(&addressof(sb))` (31.7.6.2.2 [ostream.cons]) and initializing `sb` with `basic_filebuf<charT, traits>()` (31.10.2.2 [filebuf.cons]).

    >     explicit basic_ofstream(const char* s,
    >                             ios_base::openmode mode = ios_base::out);
    >     explicit basic_ofstream(const filesystem::path::value_type* s,
    >                             ios_base::openmode mode = ios_base::out);  // wide systems only; see 31.10.1 [fstream.syn]

    > > -2- Effects: Constructs an object of class `basic_ofstream<charT, traits>`, initializing the base class with `basic_ostream<charT, traits>(&addressof(sb))` (31.7.6.2.2 [ostream.cons]) and initializing `sb` with `basic_filebuf<charT, traits>()` (31.10.2.2 [filebuf.cons]), then calls `rdbuf()->open(s, mode | ios_base::out)`. If that function returns a null pointer, calls `setstate(failbit)`.

    > […]

    >     basic_ofstream(basic_ofstream&& rhs);

    > > -4- Effects: Move constructs from the rvalue `rhs`. This is accomplished by move constructing the base class, and the contained `basic_filebuf`. Next `basic_ostream<charT, traits>::set_rdbuf(&addressof(sb))` is called to install the contained `basic_filebuf`.

11. Change 31.10.4.4 [ofstream.members] p1 as indicated:

    >     basic_filebuf<charT, traits>* rdbuf() const;

    > > -1- Returns: `const_cast<basic_filebuf<charT, traits>*>(&addressof(sb))`.

12. Change 31.10.5.2 [fstream.cons] as indicated:

    >     basic_fstream();

    > > -1- Effects: Constructs an object of class `basic_fstream<charT, traits>`, initializing the base class with `basic_iostream<charT, traits>(&addressof(sb))` (31.7.5.7.2 [iostream.cons]) and initializing `sb` with `basic_filebuf<charT, traits>()`.

    >     explicit basic_fstream(
    >       const char* s,
    >       ios_base::openmode mode = ios_base::in | ios_base::out);
    >     explicit basic_fstream(
    >       const filesystem::path::value_type* s,
    >       ios_base::openmode mode = ios_base::in | ios_base::out);  // wide systems only; see 31.10.1 [fstream.syn]

    > > -2- Effects: Constructs an object of class `basic_fstream<charT, traits>`, initializing the base class with `basic_iostream<charT, traits>(&addressof(sb))` (31.7.5.7.2 [iostream.cons]) and initializing `sb` with `basic_filebuf<charT, traits>()`, then calls `rdbuf()->open(s, mode)`. If that function returns a null pointer, calls `setstate(failbit)`.

    > […]

    >     basic_fstream(basic_fstream&& rhs);

    > > -4- Effects: Move constructs from the rvalue `rhs`. This is accomplished by move constructing the base class, and the contained `basic_filebuf`. Next `basic_istream<charT, traits>::set_rdbuf(&addressof(sb))` is called to install the contained `basic_filebuf`.

13. Change 31.10.5.4 [fstream.members] p1 as indicated:

    >     basic_filebuf<charT, traits>* rdbuf() const;

    > > -1- Returns: `const_cast<basic_filebuf<charT, traits>*>(&addressof(sb))`.

14. Change 31.11.3.1 [syncstream.osyncstream.overview], class template `basic_osyncstream` synopsis, as indicated:

    > [Drafting note: The text shown below assumes the application of the proposed resolution of issue 3127.]

    >     namespace std {
    >       template<class charT, class traits, class Allocator>
    >       class basic_osyncstream : public basic_ostream<charT, traits> {
    >       public:
    >         […]

    >         // 31.11.3.3 [syncstream.osyncstream.members], member functions
    >         void emit();
    >         streambuf_type* get_wrapped() const noexcept;
    >         syncbuf_type* rdbuf() const noexcept { return const_cast<syncbuf_type*>(&addressof(sb)); }
    >         […]
    >       };
    >     }

15. Change 31.11.3.2 [syncstream.osyncstream.cons] p1 and p4 as indicated:

    >     basic_osyncstream(streambuf_type* buf, const Allocator& allocator);

    > > -1- Effects: Initializes `sb` from `buf` and `allocator`. Initializes the base class with `basic_ostream<charT, traits>(&addressof(sb))`.

    > > -2- […]

    > > -3- […]

    >     basic_osyncstream(basic_osyncstream&& other) noexcept;

    > > -4- Effects: Move constructs the base class and `sb` from the corresponding subobjects of `other`, and calls `basic_ostream<charT, traits>::set_rdbuf(&addressof(sb))`.

    > > -5- […]