败犬日报 2026-04-13
败犬日报 2026-04-13
1. C++20 如何判断一个类 override 某个函数
可以用成员函数指针来做。(虽然这个需求有点奇怪)
cpp
#include <type_traits>
struct Base {
virtual void foo(int x);
virtual void foo(double x);
virtual void bar();
void baz(int x);
};
// 正确思路:反向检测,看 &T::foo 能否隐式赋给 void(Base::*)(int)
//
// 标准规定:void(Base::*)(int) → void(Derived::*)(int) 是隐式转换(Base→Derived 方向)
// void(Derived::*)(int) → void(Base::*)(int) 需要显式 cast(Derived→Base 方向)
//
// 因此:
// 若 T 未 override foo:&T::foo 自然是 void(Base::*)(int),赋给 void(Base::*)(int) 成功
// 若 T 已 override foo:&T::foo 是 void(T::*)(int),Derived→Base 需要显式 cast,赋值失败
//
// is_override = !能隐式赋给void(Base::*)(int)
//
// 注意:不能用 lambda 包裹,lambda body 里的类型错误是 hard error 而非 SFINAE。
// 使用 parametric requires-expression: requires(T param) { expr } 才能正确做 SFINAE。
template <typename T>
constexpr bool is_override_function_foo = requires {
requires std::is_base_of_v<Base, T>;
requires !requires(void (Base::*p)(int)) { p = &T::foo; };
};
template <typename T>
constexpr bool is_override_function_baz = requires {
requires std::is_base_of_v<Base, T>;
requires !requires(void (Base::*p)(int)) { p = &T::baz; };
};
// ---- 测试 ----
struct Derived1 : Base {
void foo(int x) override {}
void baz(int x) {}
};
struct Derived2 : Base {};
static_assert( is_override_function_foo<Derived1>);
static_assert(!is_override_function_foo<Derived2>);
static_assert(!is_override_function_foo<Base>);
static_assert( is_override_function_baz<Derived1>);
static_assert(!is_override_function_baz<Derived2>);
int main() {}