考虑这个例子
#include <iostream>
struct A{
void* operator new(std::size_t N, std::align_val_t){ // #1
return malloc(sizeof(char)* N);
}
};
int main(){
auto ptr = new A; // #2
}
GCC和叮当都抱怨
<source>:9:17: error: no matching function for call to 'operator new'
auto ptr = new A;
^
<source>:4:11: note: candidate function not viable: requires 2 arguments, but 1 was provided
void* operator new(std::size_t N, std::align_val_t){
^
1 error generated.
然而,[expr.new]p19说
重载解析是通过组装参数列表创建的函数调用来执行的。第一个参数是请求的空间量,类型为std::size_t。如果分配对象的类型具有新扩展对齐,则下一个参数是类型的对齐,类型为std::align_val_t。如果使用了新放置语法,则其表达式列表中的初始化子句是后续参数。如果没有找到匹配的函数,则
然后再次执行过载解析。
在#2
的new表达式中调用的分配函数的候选函数是#1
。第一次,组装参数列表是sizeof(A)
,它不能使#1
成为匹配函数,那么根据规则,组装参数将是sizeof(A),std::a(对齐(A))
,它可以使#1
成为匹配函数。同样,这是[expr.new]p20中记录的一个典型例子
new T
会导致以下调用之一:
为什么GCC和叮当拒绝这个例子?这是GCC和叮当的缺陷吗?或者,我误解了什么吗?
目前唯一实现CWG 2282的主要编译器是MSVC。我不知道当前有任何GCC或clang的努力或功能请求。
此外,我不认为__cpp_aligned_new
功能测试宏已针对CWG 2282进行了更新,因此您需要使用老式的编译器版本检查来确定该功能是否可用。