参数相关查找和流运算符重载

Argument Dependent Lookup and stream operators overloading

本文关键字:运算符 重载 查找 参数      更新时间:2023-10-16

>我有一个库,它公开了某种容器struct,我想在其中收集来自不同通用类型的数据,这些数据可能来自库的同一namespace以及来自std命名空间的数据,例如arraytuplepairs

此容器具有一个print_all方法,该方法将为容器中的所有元素调用operator<<。这样的运算符应该由库的用户提供。

测试库,我正在使用不同的模板参数进行T,但我不太关心print_all方法打印的内容。出于测试目的,我只关心无论测试哪个T都打印示例字符。实际上,我正在使用Google测试框架的真实代码,并且所测试方法的行为确实断言对于提供的每种数据类型都是相同的。

我试图提供operator<<的通用版本和它的两个特定版本。您可以在#if指令之间看到它们。两个编译分支都没有正确编译,很可能是因为违反了 König 查找规则。但无论如何,我想做的事情应该很容易以某种方式实现。我错过了什么?

下面是示例代码:

#include <algorithm>
#include <iostream>
#include <vector>
namespace my
{
template<typename DataType>
struct Container
{
void print_all( std::ostream& os ) const
{
std::for_each(std::begin(data),
std::end(data),
[&os](const DataType& value)
{
os << value;
});
}
std::vector<DataType> data;
};
namespace test
{
struct Data
{
std::byte data[4];
};
using Array = std::array<std::byte,4>;
#if 0
template<typename T>
std::ostream& operator<<(std::ostream& os, const T& data)
{
return os << 'X';
}
#else
std::ostream& operator<<(std::ostream& os, const Data& data)
{
return os << 'X';
}
std::ostream& operator<<(std::ostream& os, const Array& data)
{
return os << 'X';
}
#endif
void run()
{  
// Test with custom data
{ 
Container< Data> container;
container.data.resize(1);
container.print_all( std::cout );
}
// Test with std data
{
Container< Array> container;
container.data.resize(1);
container.print_all( std::cout );
}
}
} // namespace test
} // namespace my
int main()
{
my::test::run();
return 0;
}

ADL 会查看与参数关联的命名空间。

using Array = std::array<std::byte,4>;

此类型test::Array是别名。 出于 ADL 目的而与之关联的命名空间是stdtest与它无关。 ADL 只会在std中查找。 不允许在std中添加运算符;如果违反该规定,则程序格式不正确,无需诊断。 ADL 无法帮助你,因为它只帮助拥有与参数关联的命名空间的人。

您希望在std中支持的任何<<都需要在namespace my中,在print_all函数之前定义。

你的Data代码在我看来是有效的,我认为你的问题写得很差,因为它暗示os <<Data不起作用。 如果我是wromg amd,它不起作用,这是因为一些错别字;ADL 在struct上工作正常,但在别名上则不行。 将来,请在代码不起作用时包含完整的错误消息。