You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测成员是否由目标类自身声明而非继承所得?

如何检测类自身声明的成员(而非继承所得)

当然可以不借助反射机制实现这个需求!问题的核心是要区分类自身声明的成员和从基类继承来的成员,而std::experimental::is_detected会把继承的成员也判定为存在,所以我们需要更精巧的SFINAE技巧来做区分。

针对你的类型别名检测需求的解决方案

我们可以通过递归检查类的基类,判断目标成员类型是否来自继承而非自身声明。以下是修改后的代码,基于C++20的requires表达式实现通用检测:

#include <type_traits>
#include <experimental/type_traits>

struct base { using type = std::true_type; };
struct derived : public base { };

// 检测T是否自身声明了type类型别名
template <typename T, typename = void>
struct has_own_type : std::false_type {};

template <typename T>
struct has_own_type<T, std::void_t<typename T::type>> {
private:
    struct tag {};

    // 递归检查基类是否包含相同的type类型
    template <typename B>
    static constexpr bool check(std::enable_if_t<std::is_base_of_v<B, T> && !std::is_same_v<B, T>, tag>*) {
        if constexpr (requires { typename B::type; }) {
            // 如果基类B的type和T的type相同,说明是继承来的;否则继续递归检查B的基类
            return std::is_same_v<typename B::type, typename T::type> || check<B>(nullptr);
        } else {
            // 基类B没有type,终止递归
            return false;
        }
    }

    // 终止条件:没有匹配的基类
    template <typename B>
    static constexpr bool check(...) {
        return false;
    }

public:
    // 如果没有任何基类包含相同的type,说明是自身声明的
    static constexpr bool value = !check<T>(nullptr);
};

template<typename T> constexpr inline bool has_type_v = has_own_type<T>::value;

int main () {
    static_assert (has_type_v<base>);       // 成立:base自身声明了type
    static_assert (!has_type_v<derived>);   // 成立:derived的type来自继承
}

工作原理

  1. 首先,has_own_type模板先通过std::void_t检查T是否存在type类型别名。
  2. 如果存在,进入递归检查逻辑:
    • 尝试将T转换为它的任意基类B(排除自身)。
    • 检查基类B是否也存在type,并且B的type与T的type是否相同。
    • 如果找到这样的基类,说明T的type是继承来的,返回false;否则返回true。

扩展到成员变量/函数

如果要检测成员变量或成员函数是否为自身声明,可以使用另一种基于名字隐藏的技巧:

  • 创建一个包含同名成员的dummy类,让测试类和dummy类多重继承。
  • 通过检测成员指针的类型,判断测试类是否自身声明了该成员(如果测试类有自身成员,多重继承后的成员指针会指向测试类的成员,而非dummy类的)。

比如检测成员函数void func()是否为自身声明:

template <typename T>
struct has_own_func {
private:
    struct dummy { void func(); };
    struct derived : T, dummy {};

    template <typename U, U> struct check;

    // 如果derived::func指向dummy::func,说明T没有自身的func
    template <typename U>
    static std::false_type test(check<void (dummy::*)(), &U::func>*);

    // 否则说明T有自身的func
    template <typename U>
    static std::true_type test(...);

public:
    static constexpr bool value = decltype(test<derived>(nullptr))::value;
};

总结

不需要依赖反射就能实现类自身成员的检测,核心是利用SFINAE、递归基类检查或名字隐藏的C特性。上述方案都是标准C实现,不需要编译器扩展。

内容的提问来源于stack exchange,提问作者levzettelin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:25:44