<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/135249>135249</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
modernize-use-equals-delete should recommend relocating only special members to public
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
duncanthomson
</td>
</tr>
</table>
<pre>
From [the doc](https://clang.llvm.org/extra/clang-tidy/checks/modernize/use-equals-delete.html) as of v21.0.0), `modernize-use-equals-delete`:
> Identifies unimplemented private special member functions, and recommends using = delete for them.
This is great. It then goes on:
> Additionally, it recommends relocating any deleted member function from the private to the public section.
This is great for special member functions. It's not so great for non-special member functions. I think it would be better if that read (and the behavior was):
_Additionally, it recommends relocating any deleted **special** member function from the private to the public section._
The primary use of `= delete` is for special member functions. We can use it to disable copy and move support on a class. The copyability and moveability of a class is inherently part of the public interface of a class. It makes sense to me for copy and move constructors and assignment operators to be deleted in the public section of a class. The check gets this right.
But `= delete` has additional uses. It is a very useful way to "override" the C++ overload selection, implicit conversion, and binding rules. On the latter point, it helps us guard against lifetime problems when binding to const-reference function parameters. The clang-tidy check [`return-const-ref-from-parameter`](https://clang.llvm.org/extra/clang-tidy/checks/bugprone/return-const-ref-from-parameter.html) mentions the use of `= delete` for this.
In these use cases, in my opinion, it makes code far more readable if overloads are grouped together, regardless of whether they are deleted or not. The `modernize-use-equals-delete` check recommends moving deleted overloads of private functions to the `public` section of a class, while the undeleted overloads remain `private`. This feels like overreach. I think the check does this because it is motivated to modernize the pattern of suppressing special member functions, and moving these to the `public` section is the right thing to do for special member functions, not because it's the right thing in other use cases.
```cpp
class Foo
{
public:
// Skipped
private:
const Bar& validate_bar_(const Bar&);
// Prevent calling the function, above, with an expiring value.
const Bar& validate_bar_(Bar&&) = delete; // This should remain private, alongside other overloads
};
```
Related issue: https://github.com/llvm/llvm-project/issues/54276
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJykVk1v4zYQ_TX0ZWBDpj8SH3yINzWwpxZtgR6DETmS2FCkSlLOur--GOojzmY3C2wBA4ZEcubNmzePwhhN7YiOYncSu8cF9qnx4ah7p9ClxrfRu0Xp9fV4Dr4FsTulhkB7JXaPQt43KXVRbB6EPAt5VhZdvbL20q58qIU805cUcFpYJqOv_NCQeo5CnluvKTjzLwl57iMt6Z8ebVxqspRo1aTWCnkAjOAruMj1qlgVQh6E_ARiX8yHl--Oin3BkIr82_wCnzW5ZCpDEXpn2s5SSy6Rhi6YCyaC2JEyaKGltqQAVe9UMt5FToVOQyDl25acjtBH42oQm0cYckHlA6SG2tWQ78_GRDAR6kCYVvA58aKD2lME797AetDacBq09sqZTLpNFMh6hYmzobuO2fTXEKHirnBLplqSHx770hoFkfK2b4HLyL9XOSMX8i6C8wmivznhvFt-cApSY9wz1_Lie6uhJCgpJQpgKkgNco2oQch7JpaRltTgxfgALxi5vRNFTz_Fj5APQj6MAIeHn-XsaSItb2wxXKGPxGLMApsUIPYFc_oxm38RKHT5vEmcT5uIpSVQvrtmjbX-QhD7rvMhgXeAoCzGuALOz7uwNNak183Ts6-mvQzDuIYCuWSv0CFHqm5LMy5RqFDRzaks0hafKUIkFzMb7aDrt-CUdzGFXiUfYn47eAfPEviOAuaF5LnnUzuM-wazb5Ln8tgRoKYUWT4RgqmbNGr21Kf3fDcYAWd5MK1DGSYCwoWGTlW9hRe8MiIhpb9QCEaTkDJD-iTkScgT8HvrUUMkO8DLWms7a5RJXPSFQhxfc9WlcZpVF3rLWX8dKrSYRd5549Io1oZsx4YBdY9BA9ZoXExgTUXJtCwqX1pqI7ywQ0xhkx-IXgaquJOKXoXbYcCWEoWJt9lWRwrZxPdFoNQHt5zDLFnwy_kws_n_zbvs6y54x979g3yzk7NSeBwyYd8bpcFPTRzb_znTG4f9CiNlUzYO2iv4zripX5OEldcEFQZofaDsNXnMTDU3OgIGgjr4viMNydeUGgocJFCNQVuK-cZ5afICp7_mI5OmswmmoQM_vIjGxtwYV-sv3Oc52gzLV7Mhzc4xWZPYF8MMccj3Y8ToXxpjaaDWvQ8eqEXjcpwhh9gXXAI7F5GNYM0z5f2BUDWvTp7m-dR8h-X5LEnhaGWGC0o5os7OMbExzH2eioyUrS1QzNfnj-7bkaKh8R8xYAYtZb_IePP8aP-hG3MWvtZeq8g33deBjAOfBTArb5QkSzb_VNeJ4mGw3rP3vHR3EsXDaHfDTQYwjBf88Wy6jvQQY-r0uCePDpwwCLmHC1qjMdFTieFJyPvbxXxBnm7D_hbowg6s0NqRtLnUzGfpL5T1YVID6IC-dCbwzgvanlY51of5p8yc_ObLR2xOE4Yso9jkC38U2lQfI7De1dFoGvmcRZkJexzqmUkd-PmdbFaUibFnkuCtV9UmNX25Ur4V8syWNf4tu-D_JpWEPOeTbFS7rbzbL_Rxow-bAy7ouL7bbjfrvdwcFs2x2BfVZr3d3xd3SlZ0oLuyut9vC0mVqu43uDBHWchdsV0XsljfrQ-rQtKh2uz2B6XuS1ltxLbgku1snYuc-rje7OT2sLBYko3581pKRy9jSVLy13Y4ZtRlX0exLayJKb6GSSZZOn5gL6-Uj-Zy-1Hknb1-NQLZTQZtLvpgjz_P6Vjb5Sj_CwAA__-zpTZ5">