提问者:小点点

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


考虑这个例子

#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。如果使用了新放置语法,则其表达式列表中的初始化子句是后续参数。如果没有找到匹配的函数,则

  • 如果分配的对象类型具有新扩展对齐,则对齐参数将从参数列表中删除;
  • 否则,类型对齐且类型为std::align_val_t的参数将立即添加到第一个参数之后的参数列表中;

然后再次执行过载解析。

#2的new表达式中调用的分配函数的候选函数是#1。第一次,组装参数列表是sizeof(A),它不能使#1成为匹配函数,那么根据规则,组装参数将是sizeof(A),std::a(对齐(A)),它可以使#1成为匹配函数。同样,这是[expr.new]p20中记录的一个典型例子

new T会导致以下调用之一:

  • 操作符new(sizeof(T))
  • 算子new(sizeof(T), std::align_val_t(对齐(T))

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


共1个答案

匿名用户

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

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