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.4.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.3.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.3.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.4.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.5.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.3.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.3.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.5.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.6.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.6.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(i).]

    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- […]