c++ - 使用 iostream (std::wcout) 打印 CComBSTR
问题描述
以下代码:
#include <iostream>
#include <atlstr.h>
int main()
{
CComBSTR bstr(L"test");
std::wcout << bstr << std::endl;
std::wcout << static_cast<BSTR>(bstr) << std::endl;
}
印刷
033FA16C
测试
我试图用调试器调查每种情况下发生了哪些转换,但两次都进入了operator BSTR
. 那么为什么第一行打印地址而第二行打印文本呢?
解决方案
我们可以从中完全删除 ATL,因为这实际上是一个如何wcout
工作的问题。
考虑以下最小示例:
#include <iostream>
struct Foo
{
operator const wchar_t*() const { return L"what"; };
};
int main()
{
Foo f;
std::wcout << f << std::endl;
std::wcout << (const wchar_t*)f << std::endl;
}
// Output:
// 0x400934
// what
(现场演示)
In your example, the implicit conversion from CComBSTR
to BSTR
is triggered, but not by the template that instantiates operator<<(const wchar_t*)
(because the conversion is "user-defined", and user-defined conversions are not considered for template parameter matching). The only viable candidate then is the non-template operator<<(const void*)
, to which your converted BSTR
is passed.
There's actually a proposal to "fix" this in the standard (LWG 2342) and the text of the proposal explains this in more detail.
In summary:
For wide streams argument types
wchar_t const*
andwchar_t
are supported only as template parameters. User defined conversions are not considered for template parameter matching. Hence inappropriate overloads ofoperator<<
are selected when an implicit conversion is required for the argument, which is inconsistent with the behavior forchar const*
andchar
, is unexpected, and is a useless result.
The only remaining viable overload is the one taking const void*
and, since every pointer can implicitly convert to const void*
, that's what you're getting.
推荐阅读
- android-studio - org.gradle.internal.exceptions.LocationAwareException:, org.gradle.api.ProjectConfigurationException:, AndroidStudio3.5.3
- android - TextWatcher 的数据绑定在 Android 上不起作用
- python - 使用 python 脚本发送带有多个嵌入图像的 html 电子邮件
- apache-camel - 使用 REST API 向 IBM MQ 生成消息。阿帕奇骆驼
- django - 在测试用例期间出现 mongodb 连接错误?
- kubernetes - 如何在 Kubernetes 中列出服务后面的流量的所有 Pod 的名称
- java - Springboot复选框值到控制器
- flutter - 带有大量无法理解的日志的 Flutter 升级问题(虽然没有害处)
- node.js - 如何将多个数据流从单个客户端发送到 tcp 服务器
- python - 无法为 python3 安装 PySide