2011-05-23 115 views
8

如果您将任何指针指向C++流,它的地址将被放入输出中。 (显然,除非有一个更具体的输出处理程序。)禁用C++流中的指针输出?

void* px = NULL; 
const char* ps = "Test"; 
FooType* pf = ...; 
stringstream s; 
s << ps << " " << px << " " << pf "\n"; 
s.str(); // yields, for example: "Test 0 AF120089" 

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

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

const wchar_t* str = L"Test! (Wide)"; 
// ... 
cout << str << "\n"; // Ooops! Prints address of str. 

所以我想知道 - 因为我很少想要输出一个指针值,是否可以禁用指针值的格式化,以便将指针值插入流中会导致编译器错误?(指针值来输出然后可以通过使用封装型或铸造所述指针值为size_t或诸如此类可以容易地实现。)

编辑:Neil's answer光(通过提供您自己的空隙禁用无效*输出*输出运算符)我想补充一点,如果这也适用于诸如Boost.Format之类的工具,它们会隐式使用std命名空间中定义的输出运算符...

回答

3

这给出了一个编译错误在g ++中如果第二个和/或第三个输出到cout未注释:

#include <iostream> 
using namespace std; 

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


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

嗯......这看起来没问题。 “普通”的void *输出操作符是在namespace std中定义的,不是?所以如果有代码使用std的代码,这不会有帮助...? – 2011-05-23 08:44:29

+0

有点有用,但是在形式上你不允许在没有至少一个用户定义的参数类型的情况下重载操作符。 – 2011-05-23 09:27:15

+1

@Bo你认为ostream是什么? – 2011-05-23 09:29:04

4

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

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

编辑:如预期此解决方案不起作用,因为模板还捕获字符串文字。你应该更喜欢@尼尔的解决方案。

+0

酷,看起来像我们想出了几乎相同的答案! – xDD 2011-05-23 08:03:05

+0

这不会局限于全局命名空间中的代码吗?它看起来像其他命名空间中的代码会发现':: std :: operator <<'(由于'std :: cout'上的ADL)而不是':: operator <<' – MSalters 2011-05-23 08:21:46

+0

@ MSalters:On [ideone it works] (http://ideone.com/MaqNp),即使该调用来自另一个名称空间。但直觉上我会同意你的意见。 – 2011-05-23 08:25:55

1

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

#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; 
} 
+0

正如我在编辑自己的答案时所提到的,这不符合预期,因为它也会阻止您打印字符串文字。 – 2011-05-23 08:10:53

0

保持operator <<未实现指针。

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

编辑:或者更好地把一个无效的类型名称来获得编译器错误。

+0

这会给链接器错误,而不是编译器错误,不是吗? – 2011-05-23 08:07:54

+0

@尼尔,对。我会更新它。 – iammilind 2011-05-23 08:11:52