Title 2260. Explicit specializations of deleted member functions
Status dr Section 17.8.3 [temp.expl.spec]
Submitter Richard Smith

Created on 2016-04-17.00:00:00 by admin, last changed by admin.

msg5992 (view) Date: 2017-11-15.00:00:00

Proposed resolution (November, 2017)

Change 17.8.1 [temp.inst] paragraph 2, breaking the running text into bullets, as follows:

The implicit instantiation of a class template specialization causes

  • the implicit instantiation of the declarations, but not of the definitions, default arguments, or noexcept-specifiers of the non-deleted class member functions, member classes, scoped member enumerations, static data members, member templates, and friends; and

  • it causes the implicit instantiation of the definitions of deleted member functions, unscoped member enumerations, and member anonymous unions.

The implicit instantiation of a class template specialization does not cause the implicit instantiation of default arguments or noexcept-specifiers of the class member functions. [Example:

  template<class T>
  struct C {
    void f() { T x; }
    void g() = delete;
  C<void> c;                       // OK, definition of C<void>::f is not instantiated at this point
  template<> void C<int>::g() { }  // error: redefinition of C<int>::g

end example] However, for the purpose of determining whether an instantiated redeclaration is valid according to 6.2 [basic.def.odr] and 12.2 [class.mem], a declaration that corresponds to a definition in the template is considered to be a definition. [Example:

msg5891 (view) Date: 2016-12-15.00:00:00

Notes from the December, 2016 teleconference:

=delete definitions of member functions should be instantiated when instantiating a class template. That would make the example an ill-formed redefinition.

msg5890 (view) Date: 2018-03-15.00:00:00

[Accepted at the March, 2018 (Jacksonville) meeting.]

Although the Standard allows for explicitly specializing a deleted function template, member function of a class template, or member function template with a non-deleted definition, this seems to be problematic for non-template member functions of class templates. For example:

  template<typename T> struct A { 
    A(const A&) = delete; 
    A(A&&) = default; 
  template<> struct A<int>::A(const A&) { /* ... */ } 
  template<typename T> struct B { 
    virtual void f() = delete; 
  struct C : B<int> { void f() override = delete; }; // ok, overriding deleted with deleted 
  template<> void B<int>::f() {} // would make C retroactively ill-formed? 
Date User Action Args
2018-04-11 00:00:00adminsetstatus: tentatively ready -> dr
2018-02-27 00:00:00adminsetstatus: open -> tentatively ready
section: 14.7.3 [temp.expl.spec] -> 17.8.3 [temp.expl.spec]
2018-02-27 00:00:00adminsetmessages: + msg5992
2017-02-06 00:00:00adminsetmessages: + msg5891
2016-04-17 00:00:00admincreate