Is it possible to return a member variable of a class specified by a template function?

153 Views Asked by At

I am trying to generalize a function for a game engine I am writing to simplify the shader loading process.

Anyway, the difficulty arises in my attempts to templating the function. I attempted to adapt the solution found in this stack thread, and resulted in various versions of the following code without any ideal solutions:

template<typename T, typename U, U T::* x>
U testFunc(T& t)
{ 
    // Simplification of the extremely generalized function;
    // I want to return/utilize member variable x of input t
    return x;
}

struct testS1 { int a = 100; };
struct testS2 { bool b = true; };

testS1 tS1;
testS2 tS2;

// would ideally return 100
int c = testFunc<testS1, int, &testS1::a>(tS1);

// would ideally return true 
bool d = testFunc<testS2, bool, &testS2::b>(tS2);

Running the program gives the following error:

Severity: Error
Line: 46
Code: C2440
Description: 'return': cannot convert from 'int testS1::* ' to 'U'

I understand that the returned value x is not the same type as U because int testS1::* is not the same type as int.

However, I do not understand what syntax I would use to return the member variable x of type U from the struct T.

The real structs behind the placeholders testS1 and testS2 are very different from each other, so I would like to avoid using a base class/struct if at all possible.

2

There are 2 best solutions below

5
JeJo On BEST ANSWER

The other answer has already provided the syntax for accessing the pointer to the member data. In using abbreviated function template, you could do it, less verbosely the same

template<auto  x>
constexpr auto testFunc(auto const& t)
{
    return t.*x;
}

Now you call with less explicate template arguments

int c = testFunc<&testS1::a>(tS1);
bool d = testFunc<&testS2::b>(tS2);
// ...

See a demo in godbolt.org

1
YSC On
template<class T, class U, U T::*x>
U testFunc(T& t)
{
    return t.*x;
}

You simply need to dereference x to get a U.