【问题标题】:Output stream for generic container通用容器的输出流
【发布时间】:2019-12-06 13:29:12
【问题描述】:

我已经创建了这个模板函数:

// Output stream for container of type C
template<class C>
ostream& operator<<(ostream& os, const C& c) {
    os << "[";
    for (auto& i : c) {
        os << i;
        if (&i != &c.back()) os << ", ";
    }
    os << "]" << endl;
    return os;
}

但我有这个错误:

错误:重载运算符 '

错误在函数体的第一行。

【问题讨论】:

  • 你真的不应该提供这样不受约束的模板。您也不应该为您不拥有的类型重载运算符。如果是我,我会创建一个通用的 printstringify 函数并使用它来打印/返回能够打印的字符串。
  • 您已经简要描述了编译显示的代码时会发生什么:一条错误消息。您的叙述到此结束,您的叙述中似乎缺少的是一个实际问题。您的具体问题是什么?
  • 我注意到如果 v 是一个 STL 容器我不能 "cout 的重载

标签: c++ templates ostream


【解决方案1】:

此声明

template<class C>
ostream& operator<<(ostream& os, const C& c)

匹配任何类型。特别是,当您在该运算符内部调用时

os << "[";
os << i;
os << "]" << endl;

对于所有这些调用,除了现有的字符串输出运算符和endl 之外,您的运算符是一个匹配项。

不要为不属于你的类型提供运算符。相反,你可以写一个

void print(const my_container&);

或使用标签来解决歧义。例如,您可以使用

template <typename T>
struct pretty_printed_container {
    const T& container;
};

template <typename T>
pretty_printed_container<T> pretty_print(const T& t) { return {t};}

相应地修改你的输出操作符

template<class T>
std::ostream& operator<<(std::ostream& os, const pretty_printed_container<T>& c) {
    os << "[";
    for (const auto& i : c.container) {
        os << i;
        if (&i != &c.container.back()) os << ", ";
    }
    os << "]" << std::endl;
    return os;
}

然后像这样使用它

int main() {
    std::vector<int> x{1,2,3,4,5};
    std::cout << pretty_print(x);
}

输出:

[1, 2, 3, 4, 5]

【讨论】:

  • 那个pretty_print很优雅
【解决方案2】:

如果您有权访问boost 库并且不想使用pretty_printed_container,则可以实现以下内容:

#include <boost/spirit/home/support/container.hpp>

template <typename CharT, typename Traits, typename Container,
          std::enable_if_t<boost::spirit::traits::is_container<Container>::value, int> = 0>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const Container& c) {
    os << "[ ";
    for (const auto& e : c)
        os << e << " ";
    return os << "]";
}

通过这种方式,您可以直接打印您的容器,甚至是嵌套容器。

奖金: 添加此代码,您还可以将关联容器打印为std::map

/// operator<< for printing pair, this is needed to print associative containers.
template <typename T, typename U>
std::ostream& operator<<(std::ostream& os, const std::pair<T, U>& p) {
    return os << "[" << p.first << ", " << p.second << "]";
}

例如:

int main() {
    std::set<int> set{ 1, 2, 3, 4 };
    std::vector<std::vector<int>> nestedVector{ {1, 2}, {3, 4} };
    std::map<int, std::string> map{ {1, "one"}, {2, "two"}, };

    std::cout << set << '\n';
    std::cout << nestedVector << '\n';
    std::cout << map << '\n';
}

将输出:

[ 1 2 3 4 ]
[ [ 1 2 ] [ 3 4 ] ]
[ [1, one] [2, two] ]

【讨论】:

    猜你喜欢
    • 2015-08-09
    • 2020-09-19
    • 1970-01-01
    • 2019-06-14
    • 2019-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-30
    相关资源
    最近更新 更多