Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A defaulted function in C++ is an explicit instruction to the compiler to generate the standard, compiler-provided implementation for a special member function or, as of C++20, a comparison operator. By appending = default; to a function declaration, developers enforce the generation of default semantics while maintaining explicit visibility in the class interface.

Syntax

The = default specifier can be applied either inline within the class definition or out-of-line in the implementation file.
class Widget {
public:
    // Inline defaulting
    Widget() = default; 
    
    // Declaration for out-of-line defaulting
    Widget(const Widget& other); 
};

// Out-of-line defaulting
Widget::Widget(const Widget& other) = default;

Applicability

The = default syntax cannot be applied to arbitrary member functions. It is strictly limited to functions the compiler is capable of generating implicitly. These include:
  • Default constructor: ClassName()
  • Copy constructor: ClassName(const ClassName&)
  • Move constructor: ClassName(ClassName&&)
  • Copy assignment operator: ClassName& operator=(const ClassName&)
  • Move assignment operator: ClassName& operator=(ClassName&&)
  • Destructor: ~ClassName()
  • C++20 and later: The three-way comparison operator (operator<=>) and all secondary comparison operators (operator==, operator!=, operator<, operator>, operator<=, operator>=).

Technical Mechanics and Rules

Signature Matching An explicitly defaulted function must generally possess a signature compatible with the implicitly declared version. However, the C++ standard provides specific exceptions:
  1. An explicitly defaulted copy constructor or copy assignment operator is permitted to take a non-const reference (T&) even if the implicitly generated version would require a const reference (const T&).
  2. Since C++14 (via CWG 1753), the return type of a defaulted assignment operator is allowed to differ from the implicit declaration (e.g., returning void or returning by value instead of T&).
If the declaration deviates in an incompatible way, the compiler’s behavior depends on the nature of the mismatch, the C++ version, and where the function is defaulted:
  • Exception Specification Mismatch (Inline): If a function is explicitly defaulted on its first declaration but has an exception specification that is incompatible with the implicitly generated one, the function is defined as deleted (= delete). This rule has applied since C++11.
  • Signature Mismatch (Inline): If the signature deviates in other incompatible ways (such as an invalid parameter type), the program is ill-formed in C++11, C++14, and C++17. In C++20 and later, the function is instead defined as deleted.
  • Out-of-Line Mismatch: If the function is explicitly defaulted out-of-line (after its initial declaration) and possesses any mismatch in signature or exception specification, the program is ill-formed and will fail to compile.
class SignatureRules {
public:
    // Valid: The standard explicitly allows non-const references for copy operations
    SignatureRules(SignatureRules& other) = default; 

    // Valid (Since C++14): Assignment operators can return void instead of T&
    void operator=(const SignatureRules&) = default; 
};

struct ThrowingMember {
    ThrowingMember() noexcept(false) {}
};

class InlineMismatch {
    ThrowingMember member;
public:
    // C++11 and later: Defined as deleted because the explicit 'noexcept' 
    // conflicts with the implicitly generated 'noexcept(false)'
    InlineMismatch() noexcept = default; 
};
Access Control Unlike implicitly generated special member functions, which are always public, explicitly defaulted functions respect the access specifier under which they are declared. You can default a function under protected or private visibility to restrict its accessibility.
class NonConstructible {
protected:
    NonConstructible() = default; // Compiler generates it, but it is protected
};
Impact on Triviality The location of the = default declaration directly impacts the triviality of the class type (e.g., std::is_trivial_v).
  • If a special member function is defaulted on its first declaration (inline within the class body), the function is considered trivial (provided all base classes and members also have trivial corresponding operations).
  • If the function is defaulted out-of-line (after its initial declaration), it is considered non-trivial, which can affect how the object is allocated, copied, or passed through ABIs.
Implicit Deletion If a function is explicitly defaulted, but the compiler is structurally unable to generate a valid implementation, the function is implicitly defined as deleted (= delete). For example, defaulting a default constructor in a class that contains an uninitialized reference member or a const member without a default initializer will result in a deleted constructor.
class ReferenceHolder {
    int& ref;
public:
    // Implicitly becomes deleted because 'ref' cannot be default-initialized
    ReferenceHolder() = default; 
};
Master C++ with Deep Grasping Methodology!Learn More