![](/img/trans.png)
[英]Would it be possible to overload << operator for a std::map with pair std:string and std::vector<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.txt 必須與 my_pair 位於相同的命名空間中。
這樣做會導致未定義的行為,因為我會將函數添加到命名空間 std。
我想避免繼承,如struct my_pair : std::pair<int, int>
。
這個問題的解決方案是什么?
我在 OS X 上使用 clang++-3.6。
您可以在流上重載(以某種方式標記它),而不是 ADL 掛鈎要流的值:
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 掛鈎。 您可以使標記更通用(想想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;
}
}
See it Live On Coliru ,打印:
std::pair{42, I'm gonna try}
std::pair{1729, science}
這樣做會導致未定義的行為,因為我會將函數添加到命名空間 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 更像是一個構建塊,而不是應該用來表示語義信息的東西(而不是應該直接打印到流的東西)。
我知道你說過你不想要這個,但我肯定會使用繼承:
#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
字面意思是my::my_pair
std::pair<int, int>
; 你只需要它在你自己的命名空間中是一個不同的類型。 這就是繼承的用途。
我只是把這個留在這里是為了展示它是多么容易做,並解釋為什么我認為你應該這樣做。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.