关于iostream:在C ++流中禁用指针输出?

Disabling pointer output in C++ streams?

如果你把任何指针交给C++流,它的地址将被放入输出。(显然,除非有更具体的输出处理程序。)

1
2
3
4
5
6
7
void* px = NULL;
const char* ps ="Test";
FooType* pf = ...;
stringstream s;
s << ps <<"" << px <<"" << pf"
"
;
s.str(); // yields, for example:"Test 0 AF120089"

如果用户错误地试图实际打印footype的值,这可能是一个问题。

在混合宽字符和窄字符时,这也是一个问题,因为您将得到打印的地址而不是编译器错误:

1
2
3
4
const wchar_t* str = L"Test! (Wide)";
// ...
cout << str <<"
"
; // Ooops! Prints address of str.

所以我想知道-由于我很少想要输出一个指针值,是否可以禁用指针值的格式设置,以便在流中插入一个指针值会导致编译器错误?(然后,通过使用包装器类型或将指针值强制转换为大小T或其他类似的类型,可以轻松地输出指针值。)

编辑:根据Neil的回答(通过提供自己的void*输出操作符来禁用void*输出),我想补充一点,如果这也适用于boost.format之类的工具,那么隐式使用std名称空间中定义的输出操作符就更好了…


operator<<的全局模板版本似乎可以工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <boost/static_assert.hpp>

template<typename T>
std::ostream & operator<<(std::ostream & stream, T* value) {
    BOOST_STATIC_ASSERT(false);
}

int main() {
    int foo = 5;
    int * bar = &foo;

    std::cout << bar << std::endl;
}

编辑:此解决方案不能按预期工作,因为模板还捕获字符串文本。你应该更喜欢@neil的解决方案。


如果未注释第二个和/或第三个输出到cout,则在g++中会出现编译错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
using namespace std;

ostream & operator << ( const ostream &, void * ) {
}


int main() {
    int n = 0;
    cout << 0;
//  cout << &n;
//  cout << (void *) 0;
}


是的,通过提供自己的ostream运算符<<重载,可以导致编译错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>

template <typename T>
std::ostream& operator << (std::ostream& s, T* p)
{
  char ASSERT_FAILED_CANNOT_OUTPUT_POINTER[sizeof(p) - sizeof(p)];
}

int main()
{
   int x;
   int* p = &x;
   cout << p;
}


保持EDOCX1[1]没有指针提示。

1
2
template<typename T>
std::ostream& operator<<(std::ostream &stream, T* value);

编辑:或者最好是输入一个无效的类型名来获取编译器错误。