首页 > 解决方案 > 我可以重载插入运算符以获取模板化 STL 容器吗?

问题描述

我有这个关于 STL 容器的示例,所以我正在阅读它们,重复使用range-for循环来打印容器的内容对我来说太乏味了。所以我考虑过重载插入运算符<<,这样我就可以写:std::cout << container << std::endl;

template<class T>
std::ostream& operator<<(std::ostream& out, const std::list<T>& v) {
    for (const auto& e : v)
        out << e << ", ";
    return out;
}

int main() {

    std::list<int> vi{ 10, 24, 81, 57, 2019 };

    vi.pop_back();
    std::cout << vi << std::endl; // 10, 24, 81, 57,

    std::deque<std::string> names{ "Hello", "STL Containers" };
    std::cout << names << std::endl; // error here. Bacause I've not overloaded << to take a std::deque<T>


}

正如您在上面看到的,我发现打印list某种类型的 a 非常舒服。问题是我只能打印一个列表,但不能打印其他类型的容器,如 a vectoror deque...

那么我怎样才能重载<<一个容器类型T<U>或者我应该为所有容器专门化它?在一个真实的例子中我不应该这样做吗?

标签: c++

解决方案


您可以提供以下重载:

template <class...>
using void_t = void;

template <class... Args>
constexpr bool exists_t_v(){
  return std::is_same<void_t<Args...>, void>::value;
}


template <class Container, class = std::enable_if<
  exists_t_v<
    decltype(std::begin(std::declval<Container>())),
    decltype(std::end(std::declval<Container>()))
  >()
>>
std::ostream& operator<<(std::ostream& os, Container&& container){
  for(const auto& e : std::forward<Container>(container))
    os << e << ',';

  return os;
}

这将允许任何container类型Container的实例std::begin(container)std::begin(container)被定义的类型使用重载。

此类解决方案的问题之一是std::string支持以及已经为其定义std::begin()std::end()定义了自己的重载的任何类型。


推荐阅读