简单地说明operator<<
basic_ostream
和标准容器(例如vector
或pair
)的重载原因。就像string
一样。
如果有一种标准方法可以打印这些对象,那就太容易了。
我很长一段时间想知道为什么这只是一种好奇心(为每一个我希望快速输出矢量的小程序编写这样的运算符的懒惰)。但是现在我遇到了由此造成的真正的问题:
我正在实施一个库。我有一个例外类utils::exception::OutOfRange
。构造函数将表示超出范围的key
的对象作为参数。我使用stringstream
(和其他东西)来创建(全面的)错误消息:
template <class Key>
inline OutOfRange::OutOfRange(const Key &key) : Exception(2) {
//just the interesting part (a simplified version):
string_stream message;
message << "accessed at key/index '"<< key; // <-- there must be an operator<< for key
}
对于vector like container
,key
可以是int
,所以一切都很好。对于map like container
,key
可以是任何内容,但这需要必须存在operator<<
。但是如果用户希望抛出operator<<
对象,强迫用户拥有OutOfRange
是有意义的。那可以吗?
真正的困境来自于:现在我实现了Matrix
类(在同一个库中)抛出OutOfRange
。此Key
为std::pair<int, int>
。因此,我有责任为operator<<
提供std::pair
。但是,包含定义Matrix
类的标题也会带来(无声地和无关地)operator<<(ostream, std::pair)
的重载。如果用户也有这样的过载,则可能会出现冲突。
如果在标准库中为标准库中定义的容器中存在此类运算符,我觉得这一切都很容易避免。
我错过了什么吗?我创建错误的方法是错误的吗?
道歉,如果我的问题遍布整个宫殿。我试图以圆润和合乎逻辑的方式将它们捆绑在一起,不知道我成功了多少。
答案 0 :(得分:3)
标准库没有为容器重载operator<<
的原因显而易见:用户对输出的期望大不相同(单独考虑分隔符!对于vector<int>
,空格或逗号可能是好的,对于vector<vector<int>>
换行可能会更好)。没有“一个正确的”超载。这对于std::string
来说当然是不同的,std::out_of_range
主要不被认为是一个容器,而是一个字符串。
对于您的第二个问题:您可能需要重新考虑您的设计并使用operator<<
。您还可以为特定容器专门设置模板,并使用专门方法而不是#include <iostream> // std::cout
#include <iterator> // std::ostream_iterator
#include <vector> // std::vector
#include <algorithm> // std::copy
int main () {
std::vector<int> myvector;
for (int i=1; i<10; ++i) myvector.push_back(i*10);
std::ostream_iterator<int> out_it (std::cout,", ");
std::copy ( myvector.begin(), myvector.end(), out_it );
return 0;
}
执行打印。
打印范围的另一种成熟方法是使用ostream迭代器:
{{1}}
(此示例代码是从cplusplus.com复制的)
答案 1 :(得分:1)
您正在尝试写出密钥,您负责决策/设计的后果。
问题是&#34;只打印出foo&#34;类型的对象。 没有单一答案。也许对我来说,一对给出经度和纬度(因此应该以度,分,秒和小数分数显示),对于你来说,是一对数字,在笔记本中用两位小数写。这只是一个简单的案例,一些复杂的类怎么样?将公共成员写成名称/值?受保护的私人物品?静态成员?以某种方式标记基类?