c++ - 如何在 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
。当类型作为模板参数传递时,PointerToMemberDecomposer
将使用第二个定义;pointer-to-member
并且会捕捉到新的T
和P
typename
s。使用那些新typename
的;它将定义两个类型别名(ClassType
和MemberType
),因此T
可以P
在PointerToMemberDecomposer
结构之外使用。
使用时PointerToMemberDecomposer
;您应该使用在 Python 或C#中的decltype运算符。传递类型而不是自身。type
typeof
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;
但是您仍然应该使用decltype
whileDO_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
创建两个分隔的 s(或es)来检索这些类型别名;如果你想看起来像 C++ 的标准库。MemberType
type
struct
class
PointerToMemberDecomposer
推荐阅读
- kotlin - 从字符串拆分空间在 Kotlin 中不起作用
- pdf - 数字签名证书推荐
- python - 缓存 Django 页面以快速加载
- python - 如何在一行中编写嵌套的 if-elif-else 条件?
- git - Git - 从提交到主文件中永久排除文件(删除)
- symfony - 如何在我的项目 symfony 4 中卸载包 lexik / jwt-authentication-bundle
- reactjs - 如何在 React + Typescript 中为延迟加载创建 hoc
- bash - bash 星号转义在 echo 中打印 \*
- c# - .NET Core Fakes 和 VS 2019 Preview 6.9.0 Preview 2.0 找不到类型或命名空间名称
- docker - Docker 将文件从主机复制到映像