最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

In C++, is there a way to provide object member name as template parameter? - Stack Overflow

programmeradmin1浏览0评论

I have multiple classes C1, C2, etc, each has different members variables, ex: C1M1, C1M2, C2N1, C2N2. And I have a pointer to data that could be an object of C1, C2 based on initial bytes. Is there a way to write a method/template method to which I can specify, pointer to data, C1 and M1. And I can write logic on how to interpret how to read the data.

template<class C, class C::Member>
Member* Access(void* ptr) {
    C* p = reinterpret_cast<C*>(ptr);
    return &p->Member;
}

I have multiple classes C1, C2, etc, each has different members variables, ex: C1M1, C1M2, C2N1, C2N2. And I have a pointer to data that could be an object of C1, C2 based on initial bytes. Is there a way to write a method/template method to which I can specify, pointer to data, C1 and M1. And I can write logic on how to interpret how to read the data.

template<class C, class C::Member>
Member* Access(void* ptr) {
    C* p = reinterpret_cast<C*>(ptr);
    return &p->Member;
}
Share Improve this question edited Jan 30 at 7:52 pasha asked Jan 30 at 7:42 pashapasha 2,11520 silver badges37 bronze badges 8
  • 2 Better to show some code instead of writing textual description. – kiner_shah Commented Jan 30 at 7:49
  • Added sample code on what I want to do. But I'm not sure how to pass "class C::Member". – pasha Commented Jan 30 at 7:53
  • Can you show a bit more code? C::Member is a class member, how can it be a type Member*? – 3CxEZiVlQ Commented Jan 30 at 7:58
  • 2 What is a pointer to class data member "::*" and what is its use? – user7860670 Commented Jan 30 at 7:58
  • 2 What's the goal behind the question? This code seems an open door to UB. Maybe an XY problem. – Oersted Commented Jan 30 at 8:57
 |  Show 3 more comments

3 Answers 3

Reset to default 7

The shown code code in the question is unclear. A working example

template<class C, typename T, T C::*Member>
auto* Access(void* ptr) {
    C* p = static_cast<C*>(ptr);
    return &p->*Member;
}

If T is known and fixed, for example int

template<class C, int C::*Member>
int* Access(void* ptr) {
    C* p = static_cast<C*>(ptr);
    return &p->*Member;
}

As you use version C++20, you might even shorten usage code

template <auto member>
auto* Access(void* ptr) {
    return [&]<typename C, typename Ret, Ret C::* M>(std::integral_constant<Ret C::*, M>){
        C* p = reinterpret_cast<C*>(ptr);
        return &(p->*M);
        
    }(std::integral_constant<decltype(member), member>());
}

With usage similar to

C1 c1;

*Access<&C1::C1M1>(&c1) = 42;

Demo

If you think it's really needed, you can do it by applying Pointers to members like this:

struct C1 {
    int C1M1;
    int C1M2;
};

struct C2 {
    int C2N1;
    int C2N2;
};

template <class C, int C::* M_PTR>
int* Access(void* ptr) {
    C* p = reinterpret_cast<C*>(ptr);
    return &(p->*M_PTR);
}

TEST(yyy, zzz) {
    C1 c1{1, 2};
    C1 c2{3, 4};
    void* ptr1 = &c1;
    void* ptr2 = &c2;
    std::cout << *Access<C1, &C1::C1M2>(ptr1) << '\n';
    std::cout << *Access<C2, &C2::C2N1>(ptr2) << '\n';
    *Access<C2, &C2::C2N2>(ptr2) = 5;
    std::cout << *Access<C2, &C2::C2N2>(ptr2) << '\n';
}

I assumed your member type is fixed as int, if it's not, then you might need another template parameter, e.g.

template <class C, typename M, M C::* M_PTR>
M* Access(void* ptr) {
    C* p = reinterpret_cast<C*>(ptr);
    return &(p->*M_PTR);
}
发布评论

评论列表(0)

  1. 暂无评论