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
.
The paper would also resolve LWG issue 686 as NAD.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;
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 operatorunspecified-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 operatorunspecified-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 operatorunspecified-bool-type() const; ... };
Change 20.6.6.2 [util.smartptr.shared]:
namespace std { templateclass 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 ]