代码之家  ›  专栏  ›  技术社区  ›  YSC

为iterables定义模板运算符<<

  •  3
  • YSC  · 技术社区  · 6 年前

    std::ostream& operator<<(std::ostream& os, std::vector<int> const& container)
    {
        for (auto const& n : container)
            os << n << ", ";
        return os;
    }
    
    int main()
    {
        std::vector<int> data{0,1,2};
        std::cout << data << '\n';
    }
    

    demo )

    但是这个操作符的定义并不取决于我使用的是哪种容器。在这里,我想定义一个模板版本:

    template<class Iterable>
    std::ostream& operator<<(std::ostream& os, Iterable const& iterable)
    {
        for (auto const& n : iterable)
            os << n << ", ";
        return os;
    }
    
    int main()
    {
        std::vector<int> data{0,1,2};
        std::cout << data << '\n';
    }
    

    ( demo

    这就是我的编译器生气的地方,并且详细地拒绝它:

    error: ambiguous overload for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'char')
    

    为什么它不合法?我如何定义这样的运营商?

    1 回复  |  直到 6 年前
        1
  •  3
  •   YSC    6 年前

    如另一个问题所述, How do I fix “ambiguous overload” error when overloading operator<< (templated)? ,定义时 operator<<(std::ostream&, T) 对所有人 T ,则为现有 operator<<

    os << n << ", ";
            ^-- recursively calls itself? or calls the overload provided by the Standard Library?
    

    SFINAE 以确保只为iterable类型定义重载。因为 range-based for loop 基于 begin end ,我们可以用它来区分什么是 Iterable :

    template<class Iterable, class = std::void_t<decltype(begin(std::declval<Iterable>()))>>
    std::ostream& operator<<(std::ostream& os, Iterable const& iterable)
    {
        for (auto const& n : iterable)
            os << n << ", ";
        return os;
    }
    

    demo )

    std::cout << data std::cout << '\n' 调用内建重载,因为对的替换失败 Iterable = char : begin(char) 未定义。