在下面的程序中,
struct A
有默认的友元相等比较运算符,再次重新声明它以获取函数的指针(&operator==)
:
struct A {
friend constexpr bool operator ==(const A &, const A &) noexcept = default;
};
static_assert( A{} == A{} ); //if this line is removed the program fails
constexpr bool operator ==(const A &, const A &) noexcept;
static_assert( (&operator==)( A{}, A{} ) );
所有主要编译器(GCC、Clang、MSVC)都适合该程序。在线演示:https://gcc.godbolt.org/z/dhcd8esKn
但是,如果删除带有
static_assert( A{} == A{} );
的行,则相同的编译器将开始拒绝带有错误的程序:
错误:在定义之前使用了“constexpr bool operator==(const A&, const A&)”
注意:未定义的函数“operator==”不能在常量中使用
注意:失败是由于调用未定义的函数或未声明“constexpr”的函数导致的
您能否解释一下为什么上述程序仅在
static_assert( A{} == A{} );
重新声明之前存在operator==
才有效?
只要没有在任何地方使用比较运算符函数,它就没有定义。这意味着获取它的地址是行不通的。
§11.11.1 默认比较运算符函数
C 类的比较运算符函数在其第一个声明中默认且未定义为已删除,当使用 odr 或需要常量求值时,会隐式定义该函数。
线路
static_assert( A{} == A{} );
强制编译器为其生成定义,这是在尝试获取其地址时需要的。