---
title: "const and & in default member functions"
document: P3812R1
date: 2025-08-16
audience: Core Working Group,Evolution Working Group
reply-to:
  - "Jarrad J. Waterloo <descender76@gmail.com>"
---

## Changelog

### R1

- revised for better archiving

## Abstract

Allow compilers to be able to generate the default copy assignment operator for classes that have `const` and `&` members by making the class `transparently replaceable` if it has a default copy constructor. Allow compilers to be able to generate the default move assignment operator for classes that have `const` and `&` members by making the class `transparently replaceable` if it has a default move constructor. See 6.7.4 Lifetime [basic.life] ¶ 9. [N5008]

<!-- tomd:lossy-table -->

```cpp
// least privilege
class leastp final
{
public:
    leastp(std::vector<int>& v, int i)
        : v{v}, i{i} {}

    leastp(const leastp&) = default;
    leastp(leastp&&) = default;

    leastp& operator=(const leastp& other)
    {
        if (this != &other)
        {
            // lifetime of *this ends
            this->~leastp();
            // new object of type
            // leastp created
            new (this) leastp(other);
        }
        return *this;
    }

    leastp& operator=(leastp&& other)
    {
        if (this != &other)
        {
            // lifetime of *this ends
            this->~leastp();
            // new object of type
            // leastp created
            new (this) leastp(other);
        }
        return *this;
    }
    // least privilege
    constexpr size_t size() const
    {
        return v.size();
    }
private:
    std::vector<int>& v;
    const int i;
};
```

```cpp
// least privilege
class leastp final
{
public:
    leastp(std::vector<int>& v, int i)
        : v{v}, i{i} {}

    leastp(const leastp&) = default;
    leastp(leastp&&) = default;
    leastp& operator=(const leastp& other) = default;
    leastp& operator=(leastp&& other) = default;
    // least privilege
    constexpr size_t size() const
    {
        return v.size();
    }
private:
    std::vector<int>& v;
    const int i;
};
```

## Motivation

Adding this functionality would make the following enforcement unnecessary.

<!-- tomd:lossy-table -->

```cpp
class bad {
    const int i;    // bad
    string& s;      // bad
    // ...
};
```

Without this functionality, besides being more code, constness has to be enforced via even more code instead of it being enforced by use of the `const` keyword or the constness associated with references. Use of references as class members is intuitive from the standpoint constructor based dependency injection and object proxies which is useful for enforcing least privilege.

## Impact on the standard

This features removes a current limitation of default member functions. Consequently, it is not expected to break anything as this functionality isn’t supported.

[c12] C++ Core Guidelines - C.12: Don’t make data members const or
references in a copyable or movable type.

https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c12-dont-make-data-members-const-or-references-in-a-copyable-or-movable-type

[N5008] 2025. Working Draft, Programming Languages – C++.

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/n5008.pdf
