1

I need to make use of a C++'s pointer-to-member feature to make a function access a member of a substructure. Note that the object the function must operate on is not visible to the caller.

I have reduced it to the following toy problem (C++14 or later):

#include <iostream>

struct SubStruct {
   int c;
};
struct MyStruct {
   int a;
   int b;
   float f;
   SubStruct ss;
};

template <typename Tmember>
auto addTogether(Tmember member) {
    MyStruct s1 = {.a = 1, .b =2, .f =3.3, .ss = {.c = 4}};
    MyStruct s2 = {.a = 10, .b =20, .f =30.0, .ss = {.c = 40}};;

    return s1.*(member) + s2.*(member);
}

int main() {
    std::cout << "sum a = " << addTogether(&MyStruct::a) << std::endl;
    std::cout << "sum b = " << addTogether(&MyStruct::b) << std::endl;
    std::cout << "sum f = " << addTogether(&MyStruct::f) << std::endl;
    //std::cout << "sum c = " << addTogether(&MyStruct::ss::c) << std::endl; //DOES NOT WORK
    //std::cout << "sum c = " << addTogether(&MyStruct::ss.c) << std::endl; //DOES NOT WORK
    return 0;
}

The output is as expected:

sum a = 11
sum b = 22
sum f = 33.3

But how do I pass in the pointer to the data member ss.c ? See the two commented out lines in main().

Thanks.

ianinini
  • 630
  • 6
  • 13
  • 1
    Unfortunately, this is not supported in C++. Depending on how simplified your description here is, it may or may not be possible to use [`offsetof`](http://en.cppreference.com/w/cpp/types/offsetof), or make `addTogether` variadic and work if provided either a single `T MyStruct::*` or both a `MiddleType MyStruct::*` and `T MiddleType::*`, (In this case, `MiddleType` would be `SubStruct` and `T` would be `int`), or some other workaround. – Daniel H May 11 '18 at 23:23
  • 1
    (Possibly not useful depending on how you actually solve your problem, but I'd also change the signature of `addTogether` to `template auto addTogether(T MyStruct::* ptr)`, because `Tmember` looks like it's the type of the member, not the pointer-to-member type, and any valid parameter type will also match `T MyStruct::*`.) – Daniel H May 11 '18 at 23:34
  • Just out of curiosity - why do you need this for non-function members? – einpoklum May 11 '18 at 23:35
  • @DanielH Thanks for the help. Disappointing result, but the answer to the question you pointed to is very detailed. – ianinini May 12 '18 at 23:56
  • @einpoklum In my real problem I have a templated class which owns an object (a simple configuration struct with no functions). I want to be able to tell that class which data member of the object it should operate on. – ianinini May 13 '18 at 00:01
  • @ianinini: So can't you just use plain pointers? – einpoklum May 13 '18 at 00:07
  • @einpoklum I think I will have to refactor such that I can. It will "just" mean the class is exposing private data. I thought I had an elegant solution but it looks like it can't be made to work. It's not the end of the world. – ianinini May 13 '18 at 00:13

0 Answers0