This paper proposes to replace all use of private copy constructors and copy-assignement operators with deleted functions. This expresses the library specification clearly and unambiguously in code, removing the need for further explanatory text. It also brings consistency to the documentation where different clauses today vary in their use normative wording, comments in the signatures, or both to indicate the same thing.
An open issue would be whether the Deleted Functions should be declared as public or private. This paper recommends public, anticipating changes that might occur in the Modules TR that hide private declarations outside a module. Another consideration is the nature of error messages, which might be marginally clearer with public access to a deleted function than private access. However, it would not harm this paper significantly to revert to private for 0x.
There are currently no recommendations for use of the Default Function feature from the same paper. This might be considered for array, pair and tuple, but would have a larger impact on semantics. Any such change should be considered in conjunction with sequence initializers (n2215)
Change 18.6.1 [type.info]:
namespace std { class type_info { public: virtual ~type_info(); bool operator==(const type_info& rhs ) const; bool operator!=(const type_info& rhs ) const; bool before(const type_info& rhs ) const; const char* name() const;private:type_info(const type_info& rhs ) = delete; // cannot be copied type_info& operator=(const type_info& rhs ) = delete; // cannot be copied }; ...type_info(const type_info& rhs );type_info& operator=(const type_info& rhs );
-9- Effects: Copies a type_info
object.
-10- Remarks: Since the copy constructor and assignment operator for type_info
are private to the class, objects of
this type cannot be copied.
Change 20.5.5 [refwrap]:
namespace std { template <class T> class reference_wrapper : public unary_function<T1, R> // see below : public binary_function<T1, T2, R> // see below { public : // types typedef T type; typedef see below result_type; // Not always defined // construct/copy/destroy explicit reference_wrapper(T&); explicit reference_wrapper(T&&) = delete; // do not bind to temps reference_wrapper(const reference_wrapper& x); // assignment reference_wrapper& operator=(const reference_wrapper<T>& x); // access operator T& () const; T& get() const; // tcode template <class... ArgTypes> typename result_of<T(ArgTypes...)>::type operator() (ArgTypes&...) const; }; } // namespace std
Change 20.5.14.2 [func.wrap.func]:
namespace std { template<class> class function; // undefined template<class R, class... ArgTypes> class function<R(ArgTypes...)> : public unary_function<T1, R> // iff sizeof...(ArgTypes) == 1 and ArgTypes contains T1 : public binary_function<T1, T2, R> // iff sizeof...(ArgTypes) == 2 and ArgTypes contains T1 and T2 { public: ... // 20.5.14.2.3, function capacity: operator unspecified-bool-type () const; // deleted overloads close possible hole in the type system template<class R2, class... ArgTypes2> bool operator==(const function<R2(ArgTypes2...)>&) = delete; template<class R2, class... ArgTypes2> bool operator!=(const function<R2(ArgTypes2...)>&) = delete; ...private: // 20.5.14.2.6, undefined operators: template<class R2, class... ArgTypes2> bool operator==(const function<R2(ArgTypes2...)>&); template<class R2, class... ArgTypes2> bool operator!=(const function<R2(ArgTypes2...)>&);... }; } // namespace std
and remove 20.5.14.2 [func.wrap.func]:
template<class R2, class... ArgTypes2> bool operator==(const function<R2(ArgTypes2...)>&); template<class R2, class... ArgTypes2> bool operator!=(const function<R2(ArgTypes2...)>&);
-1- These member functions shall be left undefined.
-2- [ Note: the boolean-like conversion opens a loophole whereby two function instances can be compared via or !=. These undefined void operators close the loophole and ensure a compile-time error. - end note ]
Change 20.6.5.2 [unique.ptr.single]:
and 20.6.5.2.1 [unique.ptr.single.ctor]template <class T, class D = default_delete<T>> class unique_ptr { ...private:// disable copy from lvalue unique_ptr(const unique_ptr&) = delete; template <class U, class E> unique_ptr(const unique_ptr<U, E>&) = delete; unique_ptr& operator=(const unique_ptr&) = delete; template <class U, class E> unique_ptr& operator=(const unique_ptr<U, E>&) = delete; };
unique_ptr(const unique_ptr&);
-17- Declared private and left undefined to inhibit copy constructing from lvalues and const rvalues.
template <class U, class E> unique_ptr(const unique_ptr<U, E>&);
-22- Declared private and left undefined to inhibit copy constructing from lvalues and const rvalues.
and 20.6.5.2.3 [unique.ptr.single.asgn]
unique_ptr& operator=(const unique_ptr&);
-1- Declared private and left undefined to inhibit copy constructing from lvalues and const rvalues.
template <class U, class E> unique_ptr& operator=(const unique_ptr<U, E>&);
-7- Declared private and left undefined to inhibit copy constructing from lvalues and const rvalues.
and 20.6.5.3 [unique.ptr.runtime]:
template <class T, class D> class unique_ptr<T[], D> { ...private:// disable copy from lvalue unique_ptr(const unique_ptr&) = delete; unique_ptr& operator=(const unique_ptr&) = delete; };
and 20.6.5.4 [unique.ptr.compiletime]:
template <class T, class D, size_t N> class unique_ptr<T[N], D> { ...private:// disable copy from lvalue unique_ptr(const unique_ptr&) = delete; unique_ptr& operator=(const unique_ptr&) = delete; };
Change 22.1.1.1.2 [locale.facet]:
namespace std { class locale::facet { protected: explicit facet(size_t refs = 0); virtual ~facet();private:facet(const facet&) = delete;// not definedvoid operator=(const facet&) = delete;// not defined}; }
Change 22.1.1.1.3 [locale.id]:
namespace std { class locale::id { public: id();private:void operator=(const id&) = default;// not definedid(const id&) = default;// not defined}; }
Change 26.4.6 [rand.device]:
-2- If implementation limitations prevent generating non-deterministic random numbers, the implementation may employ a random number engine.
class random_device { public: // types typedef unsigned int result_type; // generator characteristics static const result_type min = see below ; static const result_type max = see below ; // constructors explicit random_device(const string& token = implementation-defined ); // generating functions result_type operator()(); // property functions double entropy() const;private:random_device(const random_device& ) = delete; void operator=(const random_device& ) = delete; };
Change 26.5.5 [template.slice.array]:
namespace std { template <class T> class slice_array { ...private:slice_array() = delete; // As implied by declaring copy constructor above }; }
and remove 26.5.5.1 [cons.slice.arr]:
slice_array();
-1- This constructor is declared to be private. This constructor need not be defined.
Change 26.5.7 [template.gslice.array]:
namespace std { template <class T> class gslice_array { ...private:gslice_array() = delete; // As implied by declaring copy constructor above }; }
and remove 26.5.7.1 [gslice.array.cons]:
gslice_array();
-1- This constructor is declared to be private. This constructor need not be defined.
Change 26.5.8 [template.mask.array]:
namespace std { template <class T> class mask_array { ...private:mask_array() = delete; // As implied by declaring copy constructor above }; }
and remove 26.5.8.1 [mask.array.cons]:
mask_array();
-1- This constructor is declared to be private. This constructor need not be defined.
Change 26.5.9 [template.indirect.array]:
namespace std { template <class T> class indirect_array { ...private:indirect_array() = delete; // As implied by declaring copy constructor above }; }
and remove 26.5.9.1 [indirect.array.cons]:
indirect_array();
-1- This constructor is declared to be private. This constructor need not be defined.
Change 27.4.2 [ios.base]:
namespace std { class ios_base { ...private:ios_base(const ios_base&) = delete; ios_base& operator=(const ios_base&) = delete; }; }
Change 27.4.4 [ios]:
namespace std { template <class charT, class traits = char_traits<charT> > class basic_ios : public ios_base { ...private:basic_ios(const basic_ios& ) = delete;// not definedbasic_ios& operator=(const basic_ios&) = delete;// not defined}; }
Change 27.6.1.1.3 [istream::sentry]
namespace std { template <class charT,class traits = char_traits<charT> > class basic_istream<charT,traits>::sentry { typedef traits traits_type; // bool ok_; exposition only public: explicit sentry(basic_istream<charT,traits>& is , bool noskipws = false); ~sentry(); operator bool() const { return ok_; }private:sentry(const sentry&) = delete;// not definedsentry& operator=(const sentry&) = delete;// not defined}; }
Change 27.6.2.4 [ostream::sentry]
namespace std { template <class charT,class traits = char_traits<charT> > class basic_ostream<charT,traits>::sentry { // bool ok_; exposition only public: explicit sentry(basic_ostream<charT,traits>& os); ~sentry(); operator bool() const { return ok_; }private:sentry(const sentry&) = delete;// not definedsentry& operator=(const sentry&) = delete;// not defined}; }