【问题标题】:How to get object type of pointer to non-static data member at compile time?如何在编译时获取指向非静态数据成员的指针的对象类型?
【发布时间】:2020-06-12 22:31:56
【问题描述】:

假设我们有一个像这样的简单数据类:

struct DataObj
{ 
  char member[32];
}

以及指向数据对象中成员的指针类型:

typedef decltype(&DataObj::member) memberObjPtr;

如何推断指针指向的成员变量的类型? 具体如何获取:

typedef myExpression<memberObjPtr>::type myType;
std::is_same<char[32],myType>::value == true

到目前为止我尝试了什么:

std::remove_pointer
std::remove_reference
std::decay

没有成功。 标准中是否隐藏着诸如 remove_member_object_pointer 之类的东西?这是我需要的,但似乎找不到..

【问题讨论】:

    标签: c++ templates typetraits member-pointers


    【解决方案1】:

    成员指针和普通指针是完全不同的类型。从成员指针到常规对象指针,您无法添加或删除任何内容。你需要一个专用的类型特征。

    // General case
    // If a type isn't supported by a partial specialization
    //  it will use this case and fail to compile
    template<class T>
    struct mbrptr_to_type;
    
    // Partial specialization that matches any data member pointer type
    // T C::* means "pointer to member of type `T` in class `C`"
    template<class T, class C>
    struct mbrptr_to_type<T C::*> {
        // Save the member type so it can be retrieved
        using type = T;
    };
    
    // Helper alias
    template<class T>
    using mbrptr_to_type_t = typename mbrptr_to_type<T>::type;
    

    使用你的测试用例:

    struct DataObj
    {
        char member[32];
    };
    
    // myType will be char[32]
    using myType = mbrptr_to_type_t<decltype(&DataObj::member)>;
    
    // Verification
    #include <type_traits>
    static_assert(std::is_same<char[32], myType>::value);
    

    现场示例:Godbolt

    【讨论】:

    • 非常感谢,正是我需要的!我从来没有想过以这种方式使用模板,并且 ::* 语法对我来说也是新的。你有没有机会知道在哪里学习这种类型特征模板编程的好资源?再次感谢
    • @robo 这种模板的使用称为部分模板特化。你可以阅读它here。这里的语法是声明pointer to data member 的方式。基本上有4种指针。常规对象指针(通常的 int* 类型)、数据成员指针(如您在此处看到的)、pointers to functions 和指向成员函数的指针(结合了最后两个)。
    【解决方案2】:

    如果您不关心引用,您可以就地执行以下操作:

    using member_t = std::remove_reference_t<decltype(std::declval<DataObj>().member)>;
    

    它不太通用,但比其他答案短一些。

    【讨论】:

    • 没想到直接用declval获取会员。但是,如果您只有memberObjPtr 这样的成员指针类型,则此方法不起作用。因此,根据 OP 实际试图解决的问题,这个答案可能比我的更好,也可能不适用。
    • 我将这个问题解释为 OP 不仅仅是一个成员指针。但我认为你的答案更加优雅和笼统。如果你只需要这样做一次,我的更快速和肮脏。
    猜你喜欢
    • 2020-12-11
    • 1970-01-01
    • 2010-11-02
    • 1970-01-01
    • 2018-01-02
    • 1970-01-01
    • 1970-01-01
    • 2012-02-10
    相关资源
    最近更新 更多