使用 iostream 打印 CComBSTR (std::wcout)
Printing CComBSTR with iostream (std::wcout)
以下code:
#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
test
我尝试使用调试器调查在每种情况下发生了哪些转换,但两次都进入了 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
(live demo)
在您的示例中,从 CComBSTR
到 BSTR
的 the implicit conversion 被触发,但 不是 由实例化 operator<<(const wchar_t*)
(因为转换为"user-defined",模板参数匹配不考虑用户自定义转换)。唯一可行的候选者是非模板 operator<<(const void*)
,您转换后的 BSTR
将传递给该模板。
实际上在标准 (LWG 2342) 中有一项针对 "fix" 的提案,提案的文本对此进行了更详细的解释。
总结:
For wide streams argument types wchar_t const*
and wchar_t
are supported only as template parameters. User defined conversions are not considered for template parameter matching. Hence inappropriate overloads of operator<<
are selected when an implicit conversion is required for the argument, which is inconsistent with the behavior for char const*
and char
, is unexpected, and is a useless result.
唯一可行的重载是采用 const void*
的重载,因为每个指针都可以隐式转换为 const void*
,这就是您得到的结果。
以下code:
#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
test
我尝试使用调试器调查在每种情况下发生了哪些转换,但两次都进入了 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
(live demo)
在您的示例中,从 CComBSTR
到 BSTR
的 the implicit conversion 被触发,但 不是 由实例化 operator<<(const wchar_t*)
(因为转换为"user-defined",模板参数匹配不考虑用户自定义转换)。唯一可行的候选者是非模板 operator<<(const void*)
,您转换后的 BSTR
将传递给该模板。
实际上在标准 (LWG 2342) 中有一项针对 "fix" 的提案,提案的文本对此进行了更详细的解释。
总结:
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.
唯一可行的重载是采用 const void*
的重载,因为每个指针都可以隐式转换为 const void*
,这就是您得到的结果。