This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 116c. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2025-03-08


2997. Defaulted functions with deleted definition

Section: 9.5.2  [dcl.fct.def.default]     Status: open     Submitter: Brian Bi     Date: 2023-08-02

When a function is defined as defaulted, the defaulted definition might be deleted. The standard requires that a non-user-provided defaulted function not be defined until it is odr-used or needed for constant evaluation (9.5.2 [dcl.fct.def.default] paragraph 5).

Consider:

  template <class T>
  struct X {
    static_assert(sizeof(T) > 1);
  };

  template <class T>
  struct Y {
    bool operator==(const Y& other) const {
      return true;
    }
  };

  struct Z {
    Y<X<char>> y;
    bool operator==(const Z& other) const = default;
  };

  int main() {
    // Z z;
    // z == z
  }

In order to determine whether the equality operator of Z is deleted, it is necessary to perform argument-dependent lookup for the equality operator that applies to Y<X<char>>, causing instantiation of the ill-formed definition of X<char>.

Clang, EDG, and MSVC perform the check at the end of the class-specifier for Z , making the program ill-formed. In contrast, gcc performs the check later, if/when the equality operator is actually used.

Whether a defaulted special member function (e.g. the copy constructor, not the equality operator function) is deleted can make a difference for class properties such as trivial copyability, affected calling conventions and thus requiring early checking. Is it worthwhile to introduce an inconsistency for the equality operator here? On the other hand, special member functions cannot cause argument-dependent lookup for their default definitions, so the problem in this issue does not arise in the first place.

A closely related question is how to interpret 13.9.2 [temp.inst] paragraph 3. Implicit instantiation of the definition of a class template specialization instantiates the definition of a member function only if the member function is deleted. Does that mean, at the point of instantiation of the class, the compiler must determine whether a defaulted definition is deleted?

The issue also arises when attempting to default equality operator functions for standard library types, e.g.

  template<class T, int N>
  struct A {
    T m[N];
    bool operator==(const A&) const = default;
  };

  struct Incomplete;
  template<class T> struct Holder { T t; };
  using H = Holder<Holder<Incomplete>*>;
  A<H, 2> a;    // error: data member of incomplete type