std :: experimental :: ostream_joiner和std :: pair [英] std::experimental::ostream_joiner and std::pair

查看:90
本文介绍了std :: experimental :: ostream_joiner和std :: pair的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在c ++ 17/g ++ 7中,终于有了长时间错过的ostream_joiner.它可以正确输出到ostream,并使用中界定界符分隔集合元素.

In c++17/g++7, there's finally the long missed ostream_joiner. It enables proper output to ostreams, separating collection elements with infix delimiters.

#include <algorithm>
#include <experimental/iterator>
#include <iostream>
#include <iterator>
#include <vector>
#include <string>

using string = std::string;
#if 1
struct pair {
    string first;
    string second;
};
#else
using pair = std::pair<string,string>;
#endif


std::ostream& operator<<(std::ostream& lhs, const pair &p) {
    return lhs << p.first << "=" << p.second;
}

int main()
{
    std::vector<pair> pairs = {{"foo", "bar"}, {"baz", "42"}};
    std::copy(std::begin(pairs),
          std::end(pairs),
          std::experimental::make_ostream_joiner(std::cout, ", "));
}

代码段成功编译并输出...

Whilst the code piece succesfully compiles and outputs ...

foo=bar, baz=42

...在代码段中将#if 1更改为#if 0使编译器抱怨缺少适当的移位运算符:

... changing the #if 1 to a #if 0 in the snippet makes the compiler complaining about missing the proper shift operator:

main.cpp:29:70:   required from here
/usr/local/include/c++/7.2.0/experimental/iterator:88:10: error: no match for 
'operator<<' (operand types are 
'std::experimental::fundamentals_v2::ostream_joiner<const char*, char, 
std::char_traits<char> >::ostream_type {aka std::basic_ostream<char>}' and 
'const std::pair<std::__cxx11::basic_string<char>, 
std::__cxx11::basic_string<char> >')
  *_M_out << __value;

有人知道为什么吗?

巴里(Barry)对这个问题给出了正确答案.但是,它不能解决问题,并且运行手动循环并不意味着重用现有的stl代码,因此问题被扩展到:

Barry has given the right answer to the question. It however does not solve the problem, and running a manual loop is not in the sense of reusing existing stl code, so the question gets extended to:

是否可以使流运算符在不污染std名称空间的情况下工作?

Is it possible to make the stream operator work without polluting the std namespace?

推荐答案

ostream_joiner实现的某个地方,将尝试进行以下操作:

Somewhere inside of the implementation of ostream_joiner, there will be an attempt to something like:

os << value;

其中osstd::basic_ostream,值是您的pair类型.为了确定该operator<<调用的操作,我们查找了在此模板定义时可见的所有重载operator<<()以及该关联命名空间中的重载.参数(称为与参数相关的查找).

where os is a std::basic_ostream and value is your pair type. In order to determine what to do for that operator<< call, we lookup all the overloads operator<<() visible at the point of definition of this template as well as as the overloads in the associated namespaces of the arguments (this is known as argument-dependent lookup).

当您使用您的 struct pair时,pair的关联命名空间为::,因此ADL会找到您的::operator<<(std::ostream&, pair const&).这种超载有效,可以选择,一切都会高兴.

When you use your struct pair, the associated namespace of pair is ::, so ADL will find your ::operator<<(std::ostream&, pair const&). This overload works, is chosen, everything is happy.

当您使用std::pair时,pair的关联命名空间是std,并且找不到使用std::pairoperator<<().因此,错误.

When you use std::pair, the associated namespace of pair is std and there is no operator<<() that can be found that takes a std::pair. Hence the error.

您可以改为在自己的命名空间中创建自己的类型,可以为其添加重载的operator<<,这可以完全是您自己的类型(问题中的方式),也可以继承:

You could instead create your own type in your own namespace for which you can add an overloaded operator<<, this can be fully your own type (the way it is in the question) or you could inherit the one in std:

struct pair : std::pair<string,string> {
    using std::pair<string,string>::pair;
};
std::ostream& operator<<(std::ostream&, my_pair const& ) {...}

或者,您不能使用make_ostream_joiner.可以替换为:

Alternatively, you could just not use make_ostream_joiner. Could replace this:

std::copy(std::begin(pairs),
      std::end(pairs),
      std::experimental::make_ostream_joiner(std::cout, ", "));

与此:

const char* delim = "";
for (auto const& pair : pairs) {
    std::cout << delim << pair; // now, our point of definition does include
                                // our operator<<() declaration, we don't need ADL
    delim = ", ";
}

这篇关于std :: experimental :: ostream_joiner和std :: pair的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆