Explicit bool for Smart Pointers

Document Number: N2435(07-0305)
2007-10-03
Alisdair Meredith <[email protected]>

Background and Rationale

One feature of the next version of the C++ Language will be Explicit Conversion operators, as descibed in n2380. One of the key motivating examples is to avoid usage of the 'conversion to unspecified bool' idiom. This is an awkward technique to teach, and should not be required learning for such an important idiom as smart pointers. It also falls under the stated goal of 'removing embarrasments' from C++0x.

The first version of this paper (N2293) raised concerns when applied to smart pointer types, so that part has been extracted into this separate proposal to be handled independantly.

Issues unique to smart pointers

There are two use cases for the unspecified-bool-idiom that an explicit bool conversion operator cannot solve - comparison with the null pointer literal and use as a function parameter/return value.

template< class T >
struct ptr {
  ...
  explicit operator bool() { return p; }
  T * p;
};

ptr< int > p;

// This code compiles with unspecified-bool-idiom
// Will not compile for an explicit bool conversion operator
if( p == 0 ) {}
if( p != 0 ) {}
if( 0 == p ) {}
if( 0 != p ) {}

// Function parameter passing and return values use copy initialization
// This code compiles with unspecified-bool-idiom
// Will not compile for an explicit bool conversion operator
void test( bool );
test( p );
bool test( ptr p ) { return p; }

Resolution

This paper proposes to replace all use of unspecified-bool-type with explicit bool conversion operators. In order to support comparison with the null pointer literal each smart pointer acquires a converting constructor for the new std::nullptr_t type. This constructor delegates to the default constructor, to initialize as an empty pointer.

In addition to solving the comparison with null pointer literal problem, the converting constructor also permits assignment from a null pointer literal, which is effectively the same as a reset.

template< class T >
struct ptr {
  ...
  ptr( nullptr_t ) : ptr() {}
  explicit operator bool() { return p; }
  T * p;
};

ptr< int > p;

// This code now compiles via nullptr_t conversting constructor
if( p == 0 ) {}
if( p != 0 ) {}
if( 0 == p ) {}
if( 0 != p ) {}

// This code also compiles via nullptr_t conversting constructor
p = 0;

The paper would also resolve LWG issue 686 as NAD.

Proposed Changes to Working Draught (n2369)