If you run the following:
#include <iostream>
int main()
{
std::cout.setf(std::ios::boolalpha);
std::cout << &main << "\n";
std::cout << (void*)&main << "\n"; // The workaround
return 0;
}
// prints something like
// true
// 0x55deee04189a
If you remove the std::cout.setf(std::ios::boolalpha)
call, it just prints 1
instead of true
.
If you look at the https://godbolt.org/z/6CFH3P assembly, you will notice that the C++
template resolution is choosing the boolean operator std::basic_ostream<char, std::char_traits<char> >::operator<<(bool)
.
After searching, I found a solution on the question How to print function pointers with cout?
The C++ Standard specifies:
4.12 Boolean conversions
1 An rvalue of arithmetic, enumeration, pointer, or pointer to member type can be converted to an rvalue of type bool.
This is the only conversion specified for function pointers.
However, it does not work for member class function pointers: https://godbolt.org/z/zBN5Va
#include<iostream>
template<class Ret, class... Args>
std::ostream& operator <<(std::ostream& os, Ret(*p)(Args...) ) {
return os << "funptr " << (void*)p;
}
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. 1
// 1. funptr 0x100401080
// 2. funptr 0x100401087
// 3. funptr 0x100401093
Is possible to fix the iostream cout/cerr member function pointers being printed as 1 or true? The goal would be to work with any free function or member class function without having to manually convert them to (void *)
pointer before sending them to std::cout
or std::cerr
.
Related questions:
Update
I tried following Dan M. tip (generic member function pointer as a template parameter):
template <typename T, typename R, typename ...Args>
std::ostream& operator <<(std::ostream& os, R (T::*p)(Args...) ) {
return os << "funptr " << (void*)p;
}
But it throws out this warning: https://godbolt.org/z/yj52hM
$ g++ -o main.exe --std=c++11 test_debugger.cpp && ./main.exe
test_debugger.cpp: In instantiation of ‘std::ostream& operator<<(std::ostream&, R (T::*)(Args ...)) [with T = test_debugger; R = int; Args = {}; std::ostream = std::basic_ostream<char>]’:
test_debugger.cpp:19:42: required from here
test_debugger.cpp:10:31: warning: converting from ‘int (test_debugger::*)()’ to ‘void*’ [-Wpmf-conversions]
return os << "funptr " << (void*)p;
^~~~~~~~
0. funptr 0x100401860
1. funptr 0x100401080
2. funptr 0x100401087
3. funptr 0x100401093
How can I properly fix the warning warning: converting from ‘int (test_debugger::*)()’ to ‘void*’ [-Wpmf-conversions]
?
main
is UB in C++. – Dowablemain
UB? – Selfdefensestd::ostream
has overloads foroperator <<
taking function pointer (making e.g.std::cout << std::endl;
possible). You have to cast pointer tovoid*
to get the address. And prefer C++ casting withstatic_cast
rather than C-style casting. – Postal