Wyz*_*a-- 6 c++ name-lookup c++14
我已经operator<<为std::pair实例定义了一个输出函数,供一些单元测试使用,如果它们没有观察到预期的值,则需要打印这些值.我的测试代码也有作为另一个有自己的类的成员保存的对operator<<- 具体来说boost::optional,但是为了示例我在Container这里定义了一个简单的类.问题是operator<<for std::pair值似乎operator<<在容器类中是不可见的.
#include <iostream>
#include <utility>
template <typename T1, typename T2>
std::ostream &operator<<(std::ostream &out, std::pair<T1, T2> const &pair) {
return out << "{ " << pair.first << ", " << pair.second << " }";
}
namespace {
template <typename T>
struct Container {
T value;
};
template <typename T>
std::ostream &operator<<(std::ostream &out, Container<T> const &container) {
return out << container.value; // Error!
}
}
int main() {
std::pair<char, int> pair { 'a', 1 };
Container<std::pair<char, int>> container { pair };
std::cout << pair << std::endl;
std::cout << container << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
输出普通对的末端附近的线路工作正常.但是当尝试在容器中输出对时,编译器无法找到operator<<for对.以下是海湾合作委员会的消息:
test.cc: In instantiation of ‘std::ostream& {anonymous}::operator<<(std::ostream&, const {anonymous}::Container<T>&) [with T = std::pair<char, int>; std::ostream = std::basic_ostream<char>]’:
test.cc:28:16: required from here
test.cc:18:16: error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘const std::pair<char, int>’)
return out << container.value;
~~~~^~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
...然后列出operator<<所考虑的所有候选函数的长列表,以及为什么每个函数都不适合(因为它们都是针对不同类型的值).我的模板std::pair不在列表中.
(这条消息来自Debian的GCC 6.3.0 -std=c++14.我从Debian的Clang 3.8.1-24 -std=c++14和Apple的Clang 1000.11.45.5(Apple LLVM 10.0.0)中得到了相同的错误,措辞不同-std=c++17.)
如果我删除Container模板及其周围的匿名命名空间operator<<,则错误消失.但这不是一个真正的解决方案,因为实际上容器boost::optional当然是命名空间boost,我无法改变它.
我不清楚为什么我的全局operator<<在命名空间内不可见,因为全局范围应该是非限定查找的搜索路径的一部分.我最好的猜测是,因为我operator<<是一个模板,模板似乎不是最初的非限定查找的一部分,所以ADL启动并找到一些其他operator<<函数定义在其中std::和作为成员std::ostream,所以查找停在那里.候选函数列表(在编译器的错误消息中)似乎与该解释一致.但是,当容器不在命名空间中时,不清楚它为什么会起作用.
有没有办法在不修改Container类的情况下完成这项工作?
(作为背景:我正在使用Boost.Test库并编写类似的行BOOST_TEST(some_func() == boost::make_optional(std::make_pair('a', 1))),其中BOOST_TEST一些宏/模板魔法提取表达式的两边并输出它们的值,如果它们不匹配.这需要值具有一个operator<<定义的.Boost提供了一个optional,我已经为std::pair它写了一个,但从前者到后者的调用就是问题所在.)
不合格的查找一次上升一级,一找到就停止.它operator<<在匿名命名空间中找到一个- 你正在呼叫的那个 - 并且在那里停止死亡.
考虑将自身pair或其pair自身的元素包装到您自己的命名空间中的包装器中.然后你可以定义一个operator<<你想做的事情并让它被ADL选中.
| 归档时间: |
|
| 查看次数: |
213 次 |
| 最近记录: |