GCC和Clang似乎不遵守分配函数调用中的重载决策

jac*_*k X 3 c++ language-lawyer

考虑一下这个例子

\n
#include <iostream>\n\nstruct A{\n    void* operator new(std::size_t N, std::align_val_t){  // #1\n        return malloc(sizeof(char)* N);\n    }\n};\nint main(){\n    auto ptr =  new A;  // #2\n}\n
Run Code Online (Sandbox Code Playgroud)\n

GCC 和 Clang 都抱怨说

\n
<source>:9:17: error: no matching function for call to \'operator new\'\n    auto ptr =  new A;\n                ^\n<source>:4:11: note: candidate function not viable: requires 2 arguments, but 1 was provided\n    void* operator new(std::size_t N, std::align_val_t){\n          ^\n1 error generated.\n
Run Code Online (Sandbox Code Playgroud)\n

然而,[expr.new] p19 说

\n
\n

重载解析是在通过组装参数列表创建的函数调用上执行的。\n第一个参数是请求的空间量,类型为 std\xe2\x80\x8b::\xe2\x80\x8bsize_\xc2\xadt。\ n如果分配对象的类型具有新扩展对齐方式,则下一个参数是类型的对齐方式,并且类型为 std\xe2\x80\x8b::\xe2\x80\x8balign_\xc2\xadval_\xc2\xadt .\n如果使用新放置语法,则其表达式列表中的初始值设定项子句是后续参数。如果没有找到匹配的函数那么

\n
\n
    \n
  • 如果分配的对象类型具有新扩展对齐方式,则从参数列表中删除对齐方式参数;
  • \n
  • 否则,作为类型对齐且类型为 std\xe2\x80\x8b::\xe2\x80\x8balign_\xc2\xadval_\xc2\xadt 的参数将立即添加到第一个参数之后的参数列表中
  • \n
\n
\n

然后再次进行重载决策

\n
\n

在新表达式中调用的分配函数的找到候选者#2#1。第一次,组装参数列表为sizeof(A),无法构成#1匹配函数,则根据规则,组装参数列表为sizeof(A),std::align_val_t(alignof(A)),可构成#1匹配函数。另外,这是一个典型的例子记录在[expr.new] p20中记录的一个典型例子

\n
\n

new T导致以下调用之一:

\n
\n
    \n
  • 运算符 new(sizeof(T))
  • \n
  • 运算符 new(sizeof(T), std::align_val_t(alignof(T)))
  • \n
\n
\n
\n

为什么 GCC 和 Clang 拒绝这个例子?这是GCC和Clang的缺陷吗?或者,我是否误解了什么?

\n

eca*_*mur 5

目前唯一实现CWG 2282 的主要编译器是MSVC。我不知道 GCC 或 clang 目前有任何努力或功能请求。

另外,我不认为__cpp_aligned_newCWG 2282 的功能测试宏已更新,因此您需要使用老式编译器版本检查来确定该功能是否可用。