1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
|
#include <memory>
#include <tuple>
#include <type_traits>
template < typename T > T* address_of( void*& next_address, std::size_t& bytes_remaining )
{
// http://en.cppreference.com/w/cpp/memory/align
// http://en.cppreference.com/w/cpp/language/alignof
auto address = static_cast<T*>( std::align( alignof(T), sizeof(T), next_address, bytes_remaining ) ) ;
if(address) { next_address = address+1 ; bytes_remaining -= sizeof(T) ; }
return address ;
}
template < typename T > std::tuple< T* > addresses_of_members( void* pv, std::size_t nbytes )
{ return std::tuple<T*>( address_of<T>( pv, nbytes ) ) ; }
template < typename T, typename... REST >
typename std::enable_if< sizeof...(REST) != 0, std::tuple< T*, REST*... > >::type
addresses_of_members( void* pv, std::size_t nbytes )
{
std::tuple<T*> first( address_of<T>( pv, nbytes ) ) ;
return std::tuple_cat( first, addresses_of_members<REST...>( pv, nbytes ) ) ;
}
#include <iostream>
#include <iomanip>
void print_members_of_unknown_object( void* address, std::size_t sz )
{
// invariant: address is the address of an object of some unknown standard layout type
// we know that the types of members in the standard layout type, in declaration order are
// int, char[16], double, long long, int[4], int
const auto ptrs = addresses_of_members< int, char[16], double, long long, int[4], int >( address, sz ) ;
std::cout << *std::get<0>(ptrs) << ", ";
std::cout << *std::get<1>(ptrs) << ", ";
std::cout << *std::get<2>(ptrs) << ", ";
std::cout << *std::get<3>(ptrs) << ", [ ";
for( int v : *std::get<4>(ptrs) ) std::cout << v << ' ' ;
std::cout << "] " << *std::get<5>(ptrs) << '\n' ;
}
int main()
{
struct tt
{
int i;
char u[16];
double d;
long long e;
int y[4];
int s;
};
tt a = { 123456, "Hello World", 69.96, 9876543210L, { 1, 2, 3, 4 }, 123 };
print_members_of_unknown_object( std::addressof(a), sizeof(a) ) ;
}
|