Why member function address are so far away from free functions? - c++

Taking this example: https://godbolt.org/z/gHqCSA
#include<iostream>
template<typename Return, typename... Args>
std::ostream& operator <<(std::ostream& os, Return(*p)(Args...) ) {
return os << (void*)p;
}
template <typename ClassType, typename Return, typename... Args>
std::ostream& operator <<(std::ostream& os, Return (ClassType::*p)(Args...) )
{
unsigned char* internal_representation = reinterpret_cast<unsigned char*>(&p);
os << "0x" << std::hex;
for(int i = 0; i < sizeof p; i++) {
os << (int)internal_representation[i];
}
return os;
}
struct test_debugger { void var() {} };
void fun_void_void(){};
void fun_void_double(double d){};
double fun_double_double(double d){return d;}
int main() {
std::cout << "0. " << &test_debugger::var << std::endl;
std::cout << "1. " << fun_void_void << std::endl;
std::cout << "2. " << fun_void_double << std::endl;
std::cout << "3. " << fun_double_double << std::endl;
}
// Prints:
// 0. 0x7018400100000000000
// 1. 0x100401080
// 2. 0x100401087
// 3. 0x100401093
I see the address of the member function is 0x7018400100000000000, which is understandable because member functions pointers have 16 bytes while free function as 0x100401080 have only 8 bytes.
However, why the member function address 0x7018400100000000000 is so far away from free function address 0x100401080? i.e., |0x7018400100000000000 - 0x100401080| = 0x70184000FFEFFBFEF80?
Why it is not closer i.e., something like 0x100401... instead of 0x701840...? Or I am printing the member function address wrong?

Your architecture is little-endian. The low byte of the address is in the first byte of p, so your address is being printed out backwards.

Fixed code which automatically detects little/big endian: https://godbolt.org/z/XSvT5R
#include <iostream>
#include <iomanip>
#include <sstream>
inline bool is_big_endian() {
long int longvalue = 1;
// https://stackoverflow.com/questions/8978935/detecting-endianness
unsigned char* representation = reinterpret_cast<unsigned char*>(&longvalue);
return ( (unsigned) representation[sizeof(long int) - 1] ) == 1;
}
template<typename Pointer>
std::ostream& print_pointer(std::ostream& os, const Pointer& pointer) {
const unsigned char* representation = (unsigned char*) &pointer;
int precision = 0;
bool haszeros = false;
unsigned firsthexdigit;
unsigned secondhexdigit;
std::ostringstream stream;
stream.flags( os.flags() );
stream << std::hex;
#define print_pointer_HEX_DIGIT \
firsthexdigit = (unsigned) representation[index] >> 4 & 0xf; \
secondhexdigit = (unsigned) representation[index] & 0xf; \
if( haszeros || firsthexdigit ) { \
precision++; \
haszeros = true ; \
stream << firsthexdigit; \
} \
if( haszeros || secondhexdigit ) { \
precision++; \
haszeros = true ; \
stream << secondhexdigit; \
}
if( is_big_endian() ) {
for(int index = 0; index < static_cast<int>(sizeof pointer); index++) {
print_pointer_HEX_DIGIT
}
}
else {
for(int index = static_cast<int>(sizeof pointer - 1); index >= 0 ; index--) {
print_pointer_HEX_DIGIT
}
}
if( os.precision() - ++precision > 0 ) {
return os << "0x" + std::string( os.precision() - ++precision, '0' ) + stream.str();
}
return os << "0x" + stream.str();
}
template<typename Return, typename... Args>
std::ostream& operator <<(std::ostream& os, Return(*pointer)(Args...) ) {
return print_pointer(os , pointer);
}
template <typename ClassType, typename Return, typename... Args>
std::ostream& operator <<(std::ostream& os, Return (ClassType::*pointer)(Args...) ) {
return print_pointer(os , pointer);
}
struct test_debugger { void var() {} };
void fun_void_void(){};
void fun_void_double(double d){};
double fun_double_double(double d){return d;}
int main() {
std::cout << "0. " << &test_debugger::var << std::endl;
std::cout << "1. " << fun_void_void << std::endl;
std::cout << "2. " << fun_void_double << std::endl;
std::cout << "3. " << fun_double_double << std::endl;
std::cout << "4. " << std::setfill('0') << std::setw(16) << fun_void_void << std::endl;
std::cout << "5. " << std::setprecision(16) << fun_void_double << std::endl;
}
// Prints:
// 0. 0x100402e80
// 1. 0x100401118
// 2. 0x10040111f
// 3. 0x10040112b
// 4. 000000x100401118
// 5. 0x0000010040111f

Related

Recognize that a value is bool in a template

This short C++17 program:
#include <iostream>
template <typename T> void output(T x)
{
if constexpr (std::is_integral<decltype(x)>::value) {
std::cout << static_cast<int>(x) << " is integral" << std::endl;
} else {
std::cout << x << " is not integral" << std::endl;
}
}
int main()
{
char x = 65;
output(x);
bool t = true;
output(t);
return 0;
}
Has this output:
65 is integral
1 is integral
In the template function named output, how can one detect that the argument x is boolean and not a number?
The plan is to output the value with std::cout << std::boolalpha <<, but only if the type is bool.
std::is_integral checks if a type is one of the following types: bool, char, char16_t, char32_t, wchar_t, short, int, long, long long (source). If you want to check if a type is the same as another type, std::is_same can be used. Both can be combined to get the wanted result:
template <typename T> void output(T x)
{
if constexpr (std::is_integral<decltype(x)>::value && !std::is_same<decltype(x), bool>::value) {
std::cout << static_cast<int>(x) << " is integral but not a boolean" << std::endl;
} else {
std::cout << x << " is not integral" << std::endl;
}
}
or, since we already know the type of decltype(x), which is T:
template <typename T> void output(T x)
{
if constexpr (std::is_integral<T>::value && !std::is_same<T, bool>::value) {
std::cout << static_cast<int>(x) << " is integral but not a boolean" << std::endl;
} else {
std::cout << x << " is not integral" << std::endl;
}
}
Another way can be to use a template specialization. This makes sure the other overload is being used to handle the boolean value.
template <typename T> void output(T x)
{
if constexpr (std::is_integral<T>::value) {
std::cout << static_cast<int>(x) << " is integral but not a boolean" << std::endl;
} else {
std::cout << x << " is not integral" << std::endl;
}
}
template <> void output(bool x)
{
std::cout << x << " is a boolean" << std::endl;
}
namespace fmt {
namespace adl {
template<class T>
void output( std::ostream& os, T const& t ) {
os << t;
}
void output( std::ostream& os, bool const& b ) {
auto old = os.flags();
os << std::boolalpha << b;
if (!( old & std::ios_base::boolalpha) )
os << std::noboolalpha; // restore state
}
template<class T>
void output_helper( std::ostream& os, T const& t ) {
output(os, t); // ADL
}
}
template<class T>
std::ostream& output( std::ostream& os, T const& t ) {
adl::output_helper( os, t );
return os;
}
}
now fmt::output( std::cout, true ) prints true, while fmt::output( std::cout, 7 ) prints 7.
You can extend fmt::output by creating a function in either fmt::adl or in the type T's namespace called output that takes a std::ostream& and a T const&.

overloading operator == for pods

I am working on some low level code with high level interfaces and felt need for comparisons operator for unit testing for plain old data types(like FILETIME struct) but since C++ doesn't even provide memberwise comparisons, so I wrote this:
template <typename Type>
std::enable_if_t<std::is_pod<Type>::value, bool> operator==(const Type& a,
const Type& b) {
return std::memcmp(&a, &b, sizeof(Type)) == 0;
}
So my question is, is this a good way or there are some hidden demons which will give me trouble later down the development cycle but it's kinda working for now.
Is C++14 available? If so, consider PFR library, which makes structures into tuples
This question is a restricted variant of Define generic comparison operator, as noted in the comments. An example of the dangers and effects of padding on the proposed operator== for POD is:
template <typename Type>
std::enable_if_t<std::is_pod<Type>::value, bool> operator==(const Type& a,
const Type& b)
{
return std::memcmp(&a, &b, sizeof(Type)) == 0;
}
struct St {
bool a_bool;
int an_int;
};
union Un {
char buff[sizeof(St)];
St st;
};
std::ostream &operator<<(std::ostream & out, const St& data)
{
return out << '{' << std::boolalpha << data.a_bool << ", " << data.an_int << '}';
}
int main()
{
Un un{{1,2,3,4,5}};
new (&un.st) St;
un.st.a_bool = true;
un.st.an_int = 5;
St x={true, 5};
std::cout << "un.a=" << un.st << '\n';
std::cout << "x=" << x << '\n';
std::cout << (x == un.st) << "\n";
return 0;
}
Both un.st and x contain the same data, but un.st contains some garbage in the padded bytes. The padded garbage makes the propose operator== return false for logically equivalent objects. Here is the output I have got for both gcc (head-9.0.0) and clang (head-8.0.0):
un.a={true, 5}
x={true, 5}
false
Update: this happens also with regular new/delete, as run on wandbox.org:
std::enable_if_t<std::is_pod<Type>::value, bool> operator==(const Type& a,
const Type& b)
{
return std::memcmp(&a, &b, sizeof(Type)) == 0;
}
struct St {
bool a_bool;
int an_int;
};
std::ostream &operator<<(std::ostream & out, const St& data)
{
return out << '{' << std::boolalpha << data.a_bool << ", " << data.an_int << '}';
}
static constexpr unsigned N_ELEMENTS = 2;
int main()
{
{
volatile char * arr = new char[sizeof(St) * N_ELEMENTS];
for (unsigned i=0; i < sizeof(St) * N_ELEMENTS ; ++i)
arr[i] = i + 1;
std::cout << "arr = " << (void*)arr << "\n";
delete[] arr;
}
St * ptr_st = new St[N_ELEMENTS];
std::cout << "ptr_st = " << ptr_st << "\n";
for (unsigned i=0 ; i != N_ELEMENTS; ++i) {
ptr_st[i].a_bool = true;
ptr_st[i].an_int = 5;
}
St x={true, 5};
std::cout << "x=" << x << '\n';
std::cout << "ptr_st[1]=" << ptr_st[1] << '\n';
std::cout << (x == ptr_st[1]) << "\n";
return 0;
}
For which the output is:
arr = 0x196dda0
ptr_st = 0x196dda0
x={true, 5}
ptr_st[1]={true, 5}
false

Convert vector<string> to other types

I've a class withmap<string,vector<string>>.
I want to give a user a member function to receive the value for a key in different formats than std::vector(string):
vector(string),
string,
vector(int),
vector(float) and
bool
example:
bool x = (bool) myClass["dummy_boolean_type"]
x = myClass["dummy_boolean_type"].as<bool>
int y = (int) myClass["dummy_boolean_type"]
Can someone have an example what is the best way to achieve it ?
(without a use in Boost)
You cannot provide your class with any member function or functions
that will support the two constructions you want:
T x = myClassInstance["key"].as<T> // (1)
T x = (T) myClassInstance["key"] // (2)
In the case of (1), the immediate reason is simply that the construction is
not legal C++. So let's suppose it is replaced by:
T x = myClassInstance["key"].as<T>() // (1a)
But this doesn't help, and the reason is the same for both (1a) and (2):
The expression myClassInstance["key"] will have to evaluate to some object e or reference to such that is returned by:
myClass::operator[](std::string const &);
This e is the vector<string> to which key maps in your
map<string,vector<string> data member of myClass. It is not myClassInstance.
So what you are asking for are member functions of myClass that will support
the constructions:
T x = e.as<T> // (1b)
T x = (T) e // (2b)
where e is an std::vector<std::string>.
Clearly, nothing you can do in myClass can address your requirement. In
(1b) and (2b), myClass is nowhere to be seen.
Is there any template member function of std::vector<std::string>:
template<typename T>
T as() const;
that has the behaviour you want for (1b)?
Does std::vector<std::string> have any template member function:
template<typename T>
operator T() const;
that has the behaviour you want for (2b)?
No and No.
However...
You can implement an as template member function of myClass that
supports conversions such as you mention. Its signature - of course -
would be:
template<typename T>
T myClass::as(std::string const & key) const;
and you would invoke it like:
T x = myClassInstance.as<T>("key") // (1c)
I'll sketch an implemention that assumes we're content with the
conversions from std::vector<std::string> to:
std::string
std::vector<int>
bool
which will be enough to get you under way.
To convert an std::vector<std::string> vs to std::string I'll concatenate
the elements of vs.
To convert an std::vector<std::string> vs to std::vector<int> I'll convert each element of vs from a decimal numeral, if I can, to the
integer the numeral represents, and return a vector of those integers. Without
prejudice to other policies I'll throw an std::invalid_argument exception
when an element doesn't trim to a decimal numeral.
I am spoilt for choice as to what you might mean by converting an std::vector<std::string>
to bool, so I will arbitrarily say that vs is true if I can convert it
to a vector<int> of which any element is non-0 and is false if I can convert
it to a vector<int> in which all elements are 0.
The sketch:
#include <type_traits>
#include <map>
#include <vector>
#include <string>
#include <algorithm>
namespace detail {
template<typename T>
struct convert_to
{
static T from(std::vector<std::string> const & vs) {
static constexpr bool always_false = !std::is_same<T,T>::value;
static_assert(always_false,
"Calling `convert_to<T>::from` for unimplemented `T`");
return *(T*)nullptr;
}
};
template<>
std::string convert_to<std::string>::from(std::vector<std::string> const & vs)
{
std::string s;
for ( auto const & e : vs ) {
s += e;
}
return s;
}
template<>
std::vector<int>
convert_to<std::vector<int>>::from(std::vector<std::string> const & vs)
{
auto lamb = [](std::string const & s) {
std::size_t lastoff = s.find_last_not_of(" \t\f\v\n\r");
int i;
try {
std::size_t nlen;
i = std::stoi(s,&nlen);
if (nlen <= lastoff) {
throw std::invalid_argument("");
}
}
catch(std::invalid_argument const & e) {
throw std::invalid_argument(
"Cannot convert \"" + s + "\" to int");
}
return i;
};
std::vector<int> vi;
std::transform(vs.begin(),vs.end(),std::back_inserter(vi),lamb);
return vi;
}
template<>
bool convert_to<bool>::from(std::vector<std::string> const & vs)
{
auto vi = convert_to<std::vector<int>>::from(vs);
for (auto const & i : vi) {
if (i) {
return true;
}
}
return false;
}
} // namespace detail
struct myClass // Your class
{
// Whatever...
std::vector<std::string> & operator[](std::string const & key) {
return _map[key];
}
template<typename T>
T as(std::string const & key) {
return detail::convert_to<T>::from(_map[key]);
}
// Whatever...
private:
std::map<std::string,std::vector<std::string>> _map;
};
The one take-away point here is the use of template<typename T>
detail::struct convert_to, with its solitary static member function:
T from(std::vector<std::string> const & vs)
which in the default instantiation will provoke a static_assert failure
reporting that no conversion to T from std::vector<std::string> has been
defined.
Then, for each type U to which you want a conversion, you have just to
write a specializing definition:
template<>
U convert_to<U>::from(std::vector<std::string> const & vs);
as you see fit, and the construction (1c) will use it as per:
template<typename T>
T myClass::as(std::string const & key) {
return detail::convert_to<T>::from(_map[key]);
}
Here's an illustrative progam you can append to the sketch:
#include <iostream>
using namespace std;
template<typename T>
static void print_vec(std::vector<T> const & v)
{
cout << "{ ";
for (auto const & e : v) {
cout << e << " ";
}
cout << "}\n";
}
static void print_vec(std::vector<std::string> const & v)
{
cout << "{ ";
for (auto const & e : v) {
cout << '\"' << e << "\" ";
}
cout << "}\n";
}
int main()
{
myClass f;
f["int_vec"] = vector<string>{"0","1 "," 2"};
cout << "f[\"int_vec\"] = "; print_vec(f["int_vec"]);
f["true_vec"] = vector<string>{"0"," 1 ","0"};
cout << "f[\"true_vec\"] = "; print_vec(f["true_vec"]);
f["false_vec"] = vector<string>{"0"," 0","0 "};
cout << "f[\"false_vec\"] = "; print_vec(f["false_vec"]);
f["not_int_vec0"] = vector<string>{"0","1","2",""};
cout << "f[\"not_int_vec0\"] = "; print_vec(f["not_int_vec0"]);
f["not_int_vec1"] = vector<string>{"0","#","2",};
cout << "f[\"not_int_vec1\"] = "; print_vec(f["not_int_vec1"]);
f["not_int_vec2"] = vector<string>{"0"," 1$","2",};
cout << "f[\"not_int_vec2\"] = "; print_vec(f["not_int_vec2"]);
cout << "f.as<string>(\"int_vec\") = \""
<< f.as<string>("int_vec") << '\"' << endl;
cout << "f.as<string>(\"true_vec\") = \""
<< f.as<string>("true_vec") << '\"' << endl;
cout << "f.as<string>(\"false_vec\") = \""
<< f.as<string>("false_vec") << '\"' << endl;
cout << "f.as<string>(\"not_int_vec0\") = \""
<< f.as<string>("not_int_vec0") << '\"' << endl;
cout << "f.as<string>(\"not_int_vec1\") = \""
<< f.as<string>("not_int_vec1") << '\"' << endl;
cout << "f.as<string>(\"not_int_vec2\") = \""
<< f.as<string>("not_int_vec2") << '\"' << endl;
vector<int> va = f.as<vector<int>>("int_vec");
cout << "f.as<vector<int>>(\"int_vec\") = ";
print_vec(f.as<vector<int>>("int_vec"));
cout << boolalpha << "f.as<bool>(\"true_vec\") = "
<< f.as<bool>("true_vec") << endl;
cout << boolalpha << "f.as<bool>(\"false_vec\") = "
<< f.as<bool>("false_vec") << endl;
try {
cout << "f.as<vector<int>>(\"not_int_vec0\")...";
auto b = f.as<vector<int>>("not_int_vec0");
(void)b;
}
catch(std::invalid_argument const & e) {
cout << e.what() << endl;
}
try {
cout << "f.as<vector<int>>(\"not_int_vec1\")...";
auto b = f.as<vector<int>>("not_int_vec1");
(void)b;
}
catch(std::invalid_argument const & e) {
cout << e.what() << endl;
}
try {
cout << "f.as<vector<int>>(\"not_int_vec2\")...";
auto b = f.as<vector<int>>("not_int_vec2");
(void)b;
}
catch(std::invalid_argument const & e) {
cout << e.what() << endl;
}
// char ch = f.as<char>("int_vec"); <- static_assert fails
return 0;
}
It outputs:
f["int_vec"] = { "0" "1 " " 2" }
f["true_vec"] = { "0" " 1 " "0" }
f["false_vec"] = { "0" " 0" "0 " }
f["not_int_vec0"] = { "0" "1" "2" "" }
f["not_int_vec1"] = { "0" "#" "2" }
f["not_int_vec2"] = { "0" " 1$" "2" }
f.as<string>("int_vec") = "01 2"
f.as<string>("true_vec") = "0 1 0"
f.as<string>("false_vec") = "0 00 "
f.as<string>("not_int_vec0") = "012"
f.as<string>("not_int_vec1") = "0#2"
f.as<string>("not_int_vec2") = "0 1$2"
f.as<vector<int>>("int_vec") = { 0 1 2 }
f.as<bool>("true_vec") = true
f.as<bool>("false_vec") = false
f.as<vector<int>>("not_int_vec0")...Cannot convert "" to int
f.as<vector<int>>("not_int_vec1")...Cannot convert "#" to int
f.as<vector<int>>("not_int_vec2")...Cannot convert " 1$" to int
(gcc 5.1, clang 3.6, C++11)

Printing zero-padded hex with std::cout [duplicate]

This question already has answers here:
How can I print 0x0a instead of 0xa using cout?
(9 answers)
Closed 6 years ago.
Say I have a dword I want to output in hex with std::cout and left-pad with zeros, so 0xabcd will be shown as 0x0000abcd. It seems like you would have to do this:
uint32_t my_int = 0xabcd;
std::cout << "0x" << std::hex << std::setw(8) << std::setfill('0')
<< my_int << std::endl;
This seems ridiculous for something that can be accomplished in C with printf("0x%08X\n", my_int);. Is there any way to make this shorter while still using std::cout for output (besides using namespace std)?
I suppose you can write a "stream manipulator". This is useful if you have multiple hex numbers you want to print in this format. This is clearly not an ideal solution, but using a wrapper type you can make your own "format flag" to toggle it. See Sticky custom stream manipulator for more information.
#include <iostream>
#include <iomanip>
static int const index = std::ios_base::xalloc();
std::ostream& hexify(std::ostream& stream) {
stream.iword(index) = 1;
return stream;
}
std::ostream& nohexify(std::ostream& stream) {
stream.iword(index) = 0;
return stream;
}
struct WrapperType {
uint32_t _m;
public:
WrapperType(uint32_t m) : _m(m)
{
}
uint32_t getm() const
{
return _m;
}
};
std::ostream& operator<< (std::ostream& os, const WrapperType& t) {
if (os.iword(index))
return os << "0x" << std::hex << std::setw(8) << std::setfill('0') << t.getm();
else
return os << t.getm();
}
int main()
{
WrapperType my_int{0xabcd};
std::cout << hexify << my_int << my_int;
std::cout << nohexify << my_int;
}
I would not change the (global) flags of a stream, just a manipulator:
#include <iostream>
#include <iomanip>
#include <limits>
template <typename T>
struct Hex
{
// C++11:
// static constexpr int Width = (std::numeric_limits<T>::digits + 1) / 4;
// Otherwise:
enum { Width = (std::numeric_limits<T>::digits + 1) / 4 };
const T& value;
const int width;
Hex(const T& value, int width = Width)
: value(value), width(width)
{}
void write(std::ostream& stream) const {
if(std::numeric_limits<T>::radix != 2) stream << value;
else {
std::ios_base::fmtflags flags = stream.setf(
std::ios_base::hex, std::ios_base::basefield);
char fill = stream.fill('0');
stream << "0x" << std::setw(width) << value;
stream.fill(fill);
stream.setf(flags, std::ios_base::basefield);
}
}
};
template <typename T>
inline Hex<T> hex(const T& value, int width = Hex<T>::Width) {
return Hex<T>(value, width);
}
template <typename T>
inline std::ostream& operator << (std::ostream& stream, const Hex<T>& value) {
value.write(stream);
return stream;
}
int main() {
std::uint8_t u8 = 1;
std::uint16_t u16 = 1;
std::uint32_t u32 = 1;
std::cout << hex(unsigned(u8), 2) << ", " << hex(u16) << ", " << hex(u32) << '\n';
}
My C++ is rusty, but how about using Boost formatting: http://www.boost.org/doc/libs/1_37_0/libs/format/index.html

Pointer-to-member: what does the pointer value represent?

I am playing with pointer-to-members and decided to actually print the values of the pointers. The result was not what I expected.
#include <iostream>
struct ManyIntegers {
int a,b,c,d;
};
int main () {
int ManyIntegers::* p;
p = &ManyIntegers::a;
std::cout << "p = &ManyIntegers::a = " << p << std::endl; // prints 1
p = &ManyIntegers::b;
std::cout << "p = &ManyIntegers::b = " << p << std::endl; // prints 1
p = &ManyIntegers::c;
std::cout << "p = &ManyIntegers::c = " << p << std::endl; // prints 1
p = &ManyIntegers::d;
std::cout << "p = &ManyIntegers::d = " << p << std::endl; // prints 1
return 0;
}
Why is the value of p always 1? Shouldn't the value of p somehow reflect which class member it points to?
As everyone has said, ostream doesn't have the appropriate operator<< defined.
Try this:
#include <cstddef>
#include <iostream>
struct Dumper {
unsigned char *p;
std::size_t size;
template<class T>
Dumper(const T& t) : p((unsigned char*)&t), size(sizeof t) { }
friend std::ostream& operator<<(std::ostream& os, const Dumper& d) {
for(std::size_t i = 0; i < d.size; i++) {
os << "0x" << std::hex << (unsigned int)d.p[i] << " ";
}
return os;
}
};
#include <iostream>
struct ManyIntegers {
int a,b,c,d;
};
int main () {
int ManyIntegers::* p;
p = &ManyIntegers::a;
std::cout << "p = &ManyIntegers::a = " << Dumper(p) << "\n";
p = &ManyIntegers::b;
std::cout << "p = &ManyIntegers::b = " << Dumper(p) << "\n";
p = &ManyIntegers::c;
std::cout << "p = &ManyIntegers::c = " << Dumper(p) << "\n";
p = &ManyIntegers::d;
std::cout << "p = &ManyIntegers::d = " << Dumper(p) << "\n";
return 0;
}
Standard ostream operator<< has no overload for pointer to member, so you pointer has been implicitly converted to bool.
p actually contains offset in object. Printing them prints implicit converted bool value true or false if they really contains some offset or not respectively. Conversion happens due to the fact that ostream's insertion member doesn't have any overload for pointers to members.
There is no overload of operator<< which takes pointer-to-member as argument. So if you try printing pointer-to-member, it implicitly converts into true which gets passed to the overload which takes bool as argument, and it prints 1 corresponds to true.
If you use std::boolalpha stream-manipulator, it will print true instead of 1:
std::cout << std::boolalpha << "p = &ManyIntegers::a = " << p ;
//^^^^^^^^^^^^^^
Output (see at ideone):
p = &ManyIntegers::a = true
A member pointer isn't necessarily a numeric value, more often than not it will be a struct or something the like. I don't think there is a way to obtain a value from a member pointer, but even if there is I don't see how that would be useful.
Here's a fully standards-compliant implementation to show the in-memory representation of the pointer-to-members:
#include <iostream>
#include <iomanip>
template<int... I> struct index_tuple { using succ = index_tuple<I..., sizeof...(I)>; };
template<int I> struct indexer { using type = typename indexer<I - 1>::type::succ; };
template<> struct indexer<0> { using type = index_tuple<>; };
template<typename T> typename indexer<sizeof(T)>::type index(const T &) { return {}; }
template<typename T> class dumper {
unsigned char buf[sizeof(T)];
friend std::ostream &operator<<(std::ostream &os, const dumper &o) {
std::ios_base::fmtflags flags{os.flags()};
std::copy_n(o.buf, sizeof(T),
std::ostream_iterator<int>(os << std::hex << std::showbase, " "));
return os << std::setiosflags(flags);
}
template<int... I> dumper (const T &t, index_tuple<I...>):
buf{reinterpret_cast<const unsigned char *>(&t)[I]...} {}
public:
dumper(const T &t): dumper(t, index(t)) {}
};
template<typename T> dumper<T> dump(const T &t) { return {t}; }
struct ManyIntegers {
int a,b,c,d;
};
int main () {
std::cout << "p = &ManyIntegers::a = " << dump(&ManyIntegers::a) << std::endl;
std::cout << "p = &ManyIntegers::b = " << dump(&ManyIntegers::b) << std::endl;
std::cout << "p = &ManyIntegers::c = " << dump(&ManyIntegers::c) << std::endl;
std::cout << "p = &ManyIntegers::d = " << dump(&ManyIntegers::d) << std::endl;
}
Output is as expected:
p = &ManyIntegers::a = 0 0 0 0
p = &ManyIntegers::b = 0x4 0 0 0
p = &ManyIntegers::c = 0x8 0 0 0
p = &ManyIntegers::d = 0xc 0 0 0