如何在C++中分解指向成员的指针(获取类和成员类型)?

我有这个场景:

#include <iostream>

class SomeClass
{
public:
    int _int;
};

#define DO_SOME_STUFF(ptr) std::cout << /* Print the typeid().hash_code() of the type which ptr is poiting to (int) */;

int main()
{
    int SomeClass::* ptr_to_int_member = &SomeClass::_int;
    DO_SOME_STUFF(ptr_to_int_member)
}

我想知道ptr指向的是哪种类型(当前是int)。知道哪个类拥有这int也很有用(目前是SomeClass)。

回答

你可以用一个“template技巧”来做到这一点:

template<typename T>
struct PointerToMemberDecomposer {};

template<typename T, typename P>
struct PointerToMemberDecomposer<P T::*>
{
    using ClassType = T;
    using MemberType = P;
};

并将您的代码更改为:

#include <iostream>

template<typename T>
struct PointerToMemberDecomposer {};

template<typename T, typename P>
struct PointerToMemberDecomposer<P T::*>
{
    using ClassType = T;
    using MemberType = P;
};

class SomeClass
{
public:
    int _int;
};

#define DO_SOME_STUFF(ptr) std::cout << typeid(PointerToMemberDecomposer<decltype(ptr)>::MemberType).hash_code();

int main()
{
    int SomeClass::* ptr_to_int_member = &SomeClass::_int;
    DO_SOME_STUFF(ptr_to_int_member)
}

定义几个模板化别名可以使代码更简洁:

#define GET_POINTER_TO_MEMBER_CLASS_TYPE(ptr) PointerToMemberDecomposer<decltype(ptr)>::ClassType
#define GET_POINTER_TO_MEMBER_MEMBER_TYPE(ptr) PointerToMemberDecomposer<decltype(ptr)>::MemberType

所以你可以DO_SOME_STUFF改为:

#define DO_SOME_STUFF(ptr) std::cout << typeid(GET_POINTER_TO_MEMBER_MEMBER_TYPE(ptr)).hash_code();

解释

这种技术称为Partial template specialization. PointerToMemberDecomposerpointer-to-member类型作为模板参数传递时,将使用的第二个定义;并会赶上新的TP typenames。使用那些新typename的;这将定义两个类型别名(ClassTypeMemberType),以便TP可以是用过的外部PointerToMemberDecomposer结构。

使用时PointerToMemberDecomposer;您应该使用decltype运算符,其作用类似于typePython 或typeofC#。decltype(x)传递类型x而不是x自身。


更新

正如463035818_is_not_a_number刚才所说,宏可以替换为templated aliases

template <typename T>
using ClassTypeFromPtrToMember_t = typename PointerToMemberDecomposer<T>::ClassType;

template <typename T>
using MemberTypeFromPtrToMember_t = typename PointerToMemberDecomposer<T>::MemberType;

但是你仍然应该使用decltypewhileDO_SOME_STUFF是一个宏而不是模板函数,我们不能ptr直接访问的类型(参见463035818_is_not_a_number 的模板函数版本的答案DO_SOME_STUFF):

#define DO_SOME_STUFF(ptr) std::cout << typeid(MemberTypeFromPtrToMember_t<decltype(ptr)>).hash_code();

在这种情况下; DO_SOME_STUFF可以转换为模板函数。但是您可能想要例如用宏参数填充非捕获 lambda;这需要DO_SOME_STUFF是一个宏。

此外,您可能要更改ClassType,并MemberTypetype与创建两个分开的structS(或classES)为检索这些类型的别名; 如果你想PointerToMemberDecomposer看起来像 C++ 的标准库。

更多细节; 见463035818_is_not_a_number 的回答

  • 非常好的答案,直到*“使其更清洁的宏”*。不。如果你想让它更干净,你可以使用类型别名。

以上是如何在C++中分解指向成员的指针(获取类和成员类型)?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>