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; }
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.
Change 20.6.5.2 [unique.ptr.single]:
template <class T, class D = default_delete<T>> class unique_ptr {
...
// constructors
unique_ptr();
explicit unique_ptr(T* p);
unique_ptr(T* p, implementation defined (see description below) d);
unique_ptr(T* p, implementation defined (see description below) d);
unique_ptr(unique_ptr&& u);
unique_ptr(nullptr_t) : unique_ptr() {}
template <class U, class E> unique_ptr(unique_ptr<U, E>&& u);
...
// observers
T& operator*() const;
T* operator->() const;
T* get() const;
deleter_type& get_deleter();
const deleter_type& get_deleter() const;
explicit operator unspecified-bool-type () const;
...
};
and 20.6.5.2.4 [unique.ptr.single.observers]
explicit operatorunspecified-bool-type() const;
-11- Returns: An unspecified value that, when used in boolean contexts, is equivalent to get() != 0.
-12- Throws: nothing.
-13- [ Note: The unspecified-bool-type is often implemented as a pointer to a private data member, avoiding many of the implicit conversion pitfalls. - end note ]
and 20.6.5.3 [unique.ptr.runtime]:
template <class T, class D> class unique_ptr<T[], D> {
...
// constructors
unique_ptr();
explicit unique_ptr(T* p);
unique_ptr(T* p, implementation defined d);
unique_ptr(T* p, implementation defined d);
unique_ptr(unique_ptr&& u);
unique_ptr(nullptr_t) : unique_ptr() {}
...
// observers
T& operator[]() const;
T* get() const;
deleter_type& get_deleter();
const deleter_type& get_deleter() const;
explicit operator unspecified-bool-type () const;
...
};
and 20.6.5.4 [unique.ptr.compiletime]:
template <class T, class D, size_t N> class unique_ptr<T[N], D> {
...
// constructors
unique_ptr();
explicit unique_ptr(T* p);
unique_ptr(T* p, implementation defined d);
unique_ptr(T* p, implementation defined d);
unique_ptr(unique_ptr&& u);
unique_ptr(nullptr_t) : unique_ptr() {}
...
// observers
T& operator[]() const;
T* get() const;
deleter_type& get_deleter();
const deleter_type& get_deleter() const;
explicit operator unspecified-bool-type () const;
...
};
Change 20.6.6.2 [util.smartptr.shared]:
namespace std {
template class shared_ptr {
...
// 20.6.6.2.1, constructors:
shared_ptr();
template<class Y> explicit shared_ptr(Y* p);
template<class Y, class D> shared_ptr(Y* p, D d);
template<class Y, class D, class A> shared_ptr(Y* p, D d, A a);
template<class Y> shared_ptr(shared_ptr<Y> const& r, T *p);
shared_ptr(shared_ptr const& r);
template<class Y> shared_ptr(shared_ptr<Y> const& r);
shared_ptr(shared_ptr&& r);
template<class Y> shared_ptr(shared_ptr<Y>&& r);
template<class Y> explicit shared_ptr(weak_ptr<Y> const& r);
template<class Y> explicit shared_ptr(auto_ptr<Y>& r);
shared_ptr(nullptr_t) : shared_ptr() {}
// 20.6.6.2.5, observers:
T* get() const;
T& operator*() const;
T* operator->() const;
long use_count() const;
bool unique() const;
explicit operator unspecified-bool-type () const; };
} // namespace std
and 20.6.6.2.5 [util.smartptr.shared.obs]
explicit operatorunspecified-bool-type() const;
-16- Returns: an unspecified value that, when used in boolean contexts, is equivalent to get() != 0.
-17- Throws: nothing.
-18- [ Note: This conversion operator allows shared_ptr objects to be used in boolean contexts. [ Example: if (p
&& p->valid()) - end example ] One possible choice for the return type is a pointer to member function, which avoids many of the implicit conversion pitfalls of a bool or void* return type. - end note ]