重载运算符>>用于 std::p air<int, int>
Overload operator>> for std::pair<int, int>
我正在尝试在std::pair<int, int>
上使用boost::lexical_cast
。
#include <iostream>
#include <utility>
#include <boost/lexical_cast.hpp>
namespace my
{
// When my_pair is a user defined type, this program compiles
// and runs without any problems.
// When declaring my_pair as an alias of std::pair<int, int>,
// it fails to compile
/*
struct my_pair
{
int first;
int second;
};
*/
using my_pair = std::pair<int, int>;
std::istream& operator>>(std::istream& stream, my_pair& pair)
{
stream >> pair.first;
stream >> std::skipws;
stream >> pair.second;
return stream;
}
}
int main()
{
my::my_pair p = boost::lexical_cast<my::my_pair>("10 10");
std::cout << p.first << " " << p.second << std::endl;
return 0;
}
如果我理解正确的话,为了使ADL工作,操作符>>必须与my_pair在同一个命名空间中,所以std.
这样做将导致未定义的行为,因为我将向命名空间std添加函数。
我想避免继承,如struct my_pair : std::pair<int, int>
。
这个问题的解决方案是什么?
我在OS x上使用clang++-3.6
您可以重载流(以某种方式标记它),而不是将值绑定到流:
int main() {
std::map<int, std::string> standback { { 42, "I'm gonna try" }, { 1729, "science" } };
streaming::tag_ostream out = std::cout;
for (auto& entry : standback)
out << entry << "n";
}
这样,您就可以在您控制的名称空间上使用ADL-hook。您可以使标记更通用(如auto out = streaming::tag(std::cout)
)。
现在,它的一个简单实现看起来像
namespace streaming {
template <typename T>
struct tag : std::reference_wrapper<T> {
using std::reference_wrapper<T>::reference_wrapper;
};
using tag_ostream = tag<std::ostream>;
template <typename T1, typename T2>
static inline tag_ostream operator<<(tag_ostream os, std::pair<T1, T2> const& p) {
os.get() << "std::pair{" << p.first << ", " << p.second << "}";
return os;
}
template <typename Other>
static inline tag_ostream operator<<(tag_ostream os, Other const& o) {
os.get() << o;
return os;
}
}
参见Live On Coliru,它打印:
std::pair{42, I'm gonna try}
std::pair{1729, science}
我知道你说过你不希望这样,但我肯定会使用inheritance:
#include <iostream>
#include <utility>
#include <boost/lexical_cast.hpp>
namespace my
{
struct my_pair : std::pair<int, int> {};
std::istream& operator>>(std::istream& stream, my_pair& pair)
{
stream >> pair.first;
stream >> std::skipws;
stream >> pair.second;
return stream;
}
}
int main()
{
my::my_pair p = boost::lexical_cast<my::my_pair>("10 10");
std::cout << p.first << " " << p.second << std::endl;
}
(现场演示)
你的my::my_pair
字面上是-a std::pair<int, int>
;您只需要在自己的名称空间中使用不同的类型即可。这就是继承的作用。
我把它留在这里只是为了展示它是多么容易做到,并解释为什么我认为你应该这样做。
这样做将导致未定义的行为,因为我将向命名空间std添加函数。
我希望避免继承,如struct my_pair: std::pair。
我想说"继承",但你忽略了它…
您可以使用封装,只需在std::pair<int,int>
上添加另一个强类型(但在这种微不足道的情况下,您可能更适合使用自定义结构-您的注释代码):
struct my_pair
{
std::pair<int,int> value;
// TODO: add any access interface here
};
std::istream& operator>>(std::istream& stream, my_pair& pair)
{
stream >> pair.value.first;
stream >> std::skipws;
stream >> pair.value.second;
return stream;
}
事实上,您可能应该这样做,因为std::pair更像是一个构建块,而不是应该用来表示语义信息的东西(也不是应该直接打印到流中的东西)。
- 为什么在全局范围内使用"extern int a"似乎不行?
- int(c) 和 c-'0' 之间的区别。C++
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 为什么野牛仍在使用"int yylex(void)",却找不到"int yylex(YYS
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 是否可以从int转换为enum类类型
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- 'short int'持有的值溢出,但"自动"不会溢出?
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- 调用'begin(int [n])'没有匹配函数
- 没有显式声明的int[]中的foreach
- 在c++中访问int到类对象的映射时出错
- 为什么我无法更改"set<set>"循环中的值<int>
- EASTL矢量<向量<int>>连续的
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- 如何加入向量&lt; int&gt;到C 中的单个INT
- 是numeric_limits&lt; int&gt; :: is_modulo从逻辑上矛盾
- 'structstd::对<int,int>'没有名为'push_back'