是否可以修复被打印为1或true的iostream cout/cerr成员函数指针? [英] Is possible to fix the iostream cout/cerr member function pointers being printed as 1 or true?

查看:141
本文介绍了是否可以修复被打印为1或true的iostream cout/cerr成员函数指针?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果运行以下命令:

#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

如果删除std::cout.setf(std::ios::boolalpha)调用,它将仅打印1而不是true.

If you remove the std::cout.setf(std::ios::boolalpha) call, it just prints 1 instead of true.

如果您查看 https://godbolt.org/z/6CFH3P 程序集,将注意到C++模板分辨率正在选择布尔运算符std::basic_ostream<char, std::char_traits<char> >::operator<<(bool).

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).

搜索后,我找到了关于问题的解决方法如何打印函数指针有cout吗?

After searching, I found a solution on the question How to print function pointers with cout?

C ++标准指定:

The C++ Standard specifies:

4.12布尔转换

4.12 Boolean conversions

1算术右值, 枚举,指针或指向 成员类型可以转换为 bool类型的右值.

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.

但是,它不适用于成员类函数指针: https://godbolt.org/z/zBN5Va

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

是否可以将iostream cout/cerr成员函数指针固定为1或true进行打印?目标将是使用任何自由函数或成员类函数,而无需在将它们发送到std::coutstd::cerr之前将它们手动转换为(void *)指针.

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.

相关问题:

  1. 使用< iostream>
  2. 打印指针
  3. 指向成员函数的指针,始终打印为"1"
  1. Printing a pointer with <iostream>
  2. Pointer to member function, always prints as "1"


更新

我尝试按照 Dan M. 提示(


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;
}

但是它抛出了以下警告: https://godbolt.org/z/yj52hM

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

如何正确解决警告warning: converting from ‘int (test_debugger::*)()’ to ‘void*’ [-Wpmf-conversions]?

推荐答案

您的重载仅对函数指针有效,因为参数是函数指针.

Your overload works only for function pointers because the argument is a function pointer.

它不适用于成员函数指针,因为成员函数指针不是函数指针,这可能会造成混淆.您可以对成员函数指针使用类似的重载:

It doesn't work for member function pointers because member function pointers are not function pointers, as confusing as that might be. You could use a similar overload for member function pointers:

template<class C, class Ret, class... Args>
std::ostream& operator <<(std::ostream& os, Ret (C::*p)(Args...)) {
    return os << "memfunptr " << "something...";
}

但是,成员函数指针不能转换为void*,因此您不能使用void*打印它们.您需要确定在他们的情况下要打印的内容.如果您的目标是仅获得一些可能与所指向的成员函数相关的输出,则可以执行以下操作:

However, member function pointers are not convertible to void* so you cannot print them using void*. You need to decide what you would like to print in their case. If your goal is to get just some output that might hopefully be related to what member function is being pointed at, then you could do something like:

unsigned char* internal_representation = reinterpret_cast<unsigned char*>(&p);
for(std::size_t i = 0; i < sizeof p; i++)
    os << std::hex << (int)internal_representation[i];


P.S.也不在所有系统上都将函数指针转换为void*.它是有条件支持的功能.至少可以在使用动态链接的所有系统上使用.


P.S. Converting a function pointer to void* is not allowed on all systems either. It is a conditionally supported feature. It'll probably work on all systems that use dynamic linking at least.

P.P.S.在所有参数均为标准类或基本类型的标准类中添加重载可能与将来的语言标准不兼容.

P.P.S. Adding overloads to standard class where all arguments are standard classes or fundamental types is probably potentially incompatible with a future language standard.

P.P.P.S.从技术上讲,不允许使用main的地址.

P.P.P.S. Taking address of main is technically not allowed.

这篇关于是否可以修复被打印为1或true的iostream cout/cerr成员函数指针?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆