The following code yields warning in G++:
#include <iostream>
#include <cstdint>
template <typename T, typename P, typename Q>
Q T::*pointer_to(P T::*p, Q P::*q)
{
typedef Q T::* output_ptr;
// warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
size_t tmp = reinterpret_cast<const size_t&>(p) + reinterpret_cast<const size_t&>(q);
return reinterpret_cast<const output_ptr&>(tmp);
}
struct A { int x; };
struct B { A a; };
int main()
{
B b = B();
b.*pointer_to(&B::a, &A::x) = 1;
std::cout << b.a.x << std::endl;
}
It works properly anyway, but that makes me worry.
What is your opinion, are these "sub-member" pointers susceptible to extra strict aliasing issues than plain member pointers?
I would recommend against doing it this way.
You stated in your comments that you tried using a nested
std::bind
, but there's an issue with the compiler version you're using. Rather than resort to the hack, I would roll my own repeated pointer to member class.The above basically provides a
make_pointer_to_sub
which takes a list of member object pointers. It accepts as its input a reference or a pointer that's convertible to the first type, and then dereferences each of the pointers in turn. It could be improved to acceptunique_ptr
orshared_ptr
, but that's for later. You use it as seen below.If you needed to, this could be assigned to a
std::function
with the appropriate arguments.