我在嵌套命名空间 (
abc::util
) 中有一个类型及其重载 operator<<
。但是,尝试从外部命名空间 (abc
) 调用它会导致编译错误:
<source>: In function 'void abc::func(std::ostringstream&, const Foo&)':
<source>:38:9: error: no match for 'operator<<' (operand types are 'std::basic_ostream<char>' and 'const abc::Foo::MyType' {aka 'const abc::util::MyType'})
37 | oss << ';'
| ~~~~~~~~~~
| |
| std::basic_ostream<char>
38 | << foo.value;
| ^~ ~~~~~~~~~
| |
| const abc::Foo::MyType {aka const abc::util::MyType}
这是最小的例子:
#include <sstream>
#include <string>
#include <print>
namespace abc::util
{
struct MyType
{
std::string value;
};
std::ostringstream&
operator<<( std::ostringstream& oss, const MyType& some_value )
{
oss << some_value.value;
return oss;
}
}
namespace abc
{
struct Foo
{
using MyType = util::MyType;
MyType value { "12345" };
};
void
func( std::ostringstream& oss, const Foo& foo )
{
oss << ';'
<< foo.value; // does not compile
// oss << ';';
// oss << foo.value; compiles fine
}
}
int main( )
{
std::ostringstream oss;
abc::func( oss, abc::Foo { } );
std::println( "{}", oss.view( ) );
}
我不太清楚为什么会这样编译:
oss << ';';
oss << foo.value;
但这不是:
oss << ';'
<< foo.value;
有什么理由吗?
问题:
oss << ';'
返回 ostream&
而不是 ostringstream&
,因此您在尝试使用以下命令时无法链接调用:
oss << ';' << foo.value;
请注意,命名空间与此问题无关。
解决方案:
一个有效的解决方案是将您的
operator<<
和 func
更改为使用 std::ostream
而不是 std::ostringstream
。
即:
变化:
std::ostringstream& operator<<( std::ostringstream& oss, const MyType& some_value)
致:
std::ostream& operator<<( std::ostream& oss, const MyType& some_value)
并改变:
void func(std::ostringstream& oss, const Foo& foo)
致:
void func(std::ostream& oss, const Foo& foo)
请注意,您仍然可以将
main()
中的这些函数与 std::ostringstream oss
一起使用,因为 ostringstream
源自 ostream
。
因此这个解决方案只会让你的代码更加通用。
最后一点:
您在评论中提到,您不需要使用
std::cout
或 std::ofstream
之类的东西使这些类型可打印,但我不明白为什么这是反对此解决方案的论据: