为了表明我想要的在 C++ 中并非不可能,我将提供以下解决方案:
// Example program
#include <iostream>
#include <string>
#include <memory>
template<typename T, typename P>
class MemberPointer
{
public:
virtual P& access(T& obj) = 0;
};
template<typename T, typename P>
class SimpleMemberPointer : public MemberPointer<T, P>
{
P T::*ptr;
public:
SimpleMemberPointer(P T::*ptr): ptr(ptr){}
P& access(T& obj) override
{
return obj.*ptr;
}
using object = T;
using property = P;
};
template<typename Ptr, typename P>
class NestedMemberPointer : public MemberPointer<typename Ptr::object, P>
{
public:
using object = typename Ptr::object;
using property = P;
private:
using intermediate = typename Ptr::property;
Ptr parent;
P intermediate::*ptr;
public:
NestedMemberPointer(Ptr parent, P intermediate::*ptr): parent(parent), ptr(ptr){}
P& access(object& obj) override
{
return parent.access(obj).*ptr;
}
};
示例使用代码:
class Person
{
public:
std::string name;
struct Address{
std::string street;
}address;
};
void test(Person &p, MemberPointer<Person, std::string> &ptr)
{
std::cout << ptr.access(p) << std::endl;
}
int main()
{
Person p{"Jim", {"Street"}};
std::unique_ptr<MemberPointer<Person, std::string>> ptr = std::make_unique<SimpleMemberPointer<Person, std::string>>(&Person::name);
std::unique_ptr<MemberPointer<Person, std::string>> ptr2 = std::make_unique<NestedMemberPointer<SimpleMemberPointer<Person, Person::Address>, std::string>>(SimpleMemberPointer<Person, Person::Address>{&Person::address}, &Person::Address::street);
test(p, *ptr);
test(p, *ptr2);
}
ptr 和 ptr2 是相同类型的变量,尽管引用不同深度的成员,正如我想要的那样。
如果执行程序打印
Jim
Street
现在这个解决方案的唯一问题是它不是很简单而且性能也不是很好,因为它需要相当复杂的变量定义并且需要多态性来区分不同的路径