Title
No formatted output operator for nullptr
Status
c++17
Section
[output.streams]
Submitter
Matt Austern

Created on 2012-12-07.00:00:00 last changed 90 months ago

Messages

Date: 2016-08-05.21:58:45

Proposed resolution:

This wording is relative to N4606

  1. Insert the signature into [ostream], class template basic_ostream synopsis, as follows:

    [Drafting notes: Why member? Don't want to define a new category of inserters just for this.]

    namespace std {
      template <class charT, class traits = char_traits<charT> >
      class basic_ostream
        : virtual public basic_ios<charT, traits> {
      public:
        […]
        basic_ostream<charT, traits>& operator<<(const void* p);
        basic_ostream<charT, traits>& operator<<(nullptr_t);
        basic_ostream<charT, traits>& operator<<(
          basic_streambuf<char_type, traits>* sb);
        […]
      };
    
  2. Append the following new paragraphs to [ostream.inserters]:

    basic_ostream<charT, traits>& operator<<
      (basic_streambuf<charT, traits>* sb);
    

    […]

    -10- Returns: *this.

    basic_ostream<charT, traits>& operator<<(nullptr_t);
    

    -??- Effects: Equivalent to return *this << s; where s is an implementation-defined NTCTS.

Date: 2016-08-06.21:12:20

[ 2016-08 Chicago ]

The group consensus is that we only output nullptr because it is of a fundamental type, causing problems in functions doing forwarding, and we don't want to read it back.

Fri PM: Move to Tentatively Ready

Date: 2016-08-03.12:32:27

[ 2016-08 Chicago ]

Tues PM: General agreement on providing the overload; discussion on what it should say.

Polls:
Matt's suggestion (in the issue): 2/0/6/2/2/
Unspecified output: 3/2/5/0/1
Specified output: 1/1/6/3/0

Move to Open

Date: 2016-08-02.15:24:00

[ 2016-08 Chicago ]

Zhihao recommends NAD:

nullptr is printable if being treated as void*, but causes UB if being treated as char cv*. Capturing this ambigurity at compile time and avoid a runtime UB is a good thing.

Date: 2016-01-15.00:00:00

[ 2016-01-18, comments from Mike and Ville collected by Walter Brown ]

Mike Miller: "Changing overload resolution sounds like something that should be considered by EWG before CWG […]"

Ville: "Agreed, such a change would be Evolutionary. Personally, I think it would also be wrong, because I don't see how void* is the right choice to prefer in the case of code that is currently ambiguous. Sure, it would solve this particular library issue, but it seemingly has wider repercussions. If LWG really wants to, EWG can certainly discuss this issue, but I would recommend solving it on the LWG side (which doesn't mean that the standard necessarily needs to change, I wouldn't call it far-fetched to NAD it)."

Date: 2014-06-10.17:47:53

When I write

std::cout << nullptr << std::endl;

I get a compilation error, "ambiguous overload for 'operator<<' in 'std::cout << nullptr'". As far as I can tell, the compiler is right to issue that error. There are inserters for const void*, const char*, const signed char*, and const unsigned char*, and none for nullptr_t, so the expression really is ambiguous.

Proposed wording:

The obvious library solution is to add a nullptr_t overload, which would be defined something like

template<class C, class T>
basic_ostream<C, T>& operator<<(basic_ostream<C, T>& os, nullptr_t) 
{ 
  return os << (void*) nullptr; 
}

We might also consider addressing this at a core level: add a special-case language rule that addresses all cases where you write f(nullptr) and f is overloaded on multiple pointer types. (Perhaps a tiebreaker saying that void* is preferred in such cases.)

History
Date User Action Args
2017-07-30 20:15:43adminsetstatus: wp -> c++17
2016-11-14 03:59:28adminsetstatus: pending -> wp
2016-11-14 03:55:22adminsetstatus: ready -> pending
2016-08-06 21:12:20adminsetstatus: open -> ready
2016-08-03 17:33:06adminsetmessages: + msg8367
2016-08-03 17:33:06adminsetmessages: + msg8366
2016-08-03 12:32:27adminsetmessages: + msg8352
2016-08-03 12:32:27adminsetstatus: new -> open
2016-08-02 15:24:00adminsetmessages: + msg8311
2016-01-18 18:08:19adminsetmessages: + msg7691
2012-12-07 00:00:00admincreate