Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I overload the insertion operator to take a templated-STL container? [duplicate]

Tags:

c++

I have this example which is about STL containers so i'm reading about them, It gets so tedious for me to repeatedly use a range-for loop to print the content of a container. So I thought about overloading the insertion operator << thus I can write: 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>


}

As you can see above I find it so comfortable to print a list of some type. The problem is I can only print a list but not other sort of container like a vector or deque...

So how can I overload << to take a container of type T<U> or Should I specialize it for all the containers? In a real example Shouldn't I do that?

like image 670
Itachi Uchiwa Avatar asked Nov 07 '22 14:11

Itachi Uchiwa


1 Answers

You could provide the following overload :

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;
}

This will let any instance container of the type Container for which std::begin(container) and std::begin(container) are defined to use the overload.

One of the issues with solutions like these is std::string support as well as any type that already provide its own overload for which std::begin() and std::end() are defined.

like image 51
Vivick Avatar answered Nov 15 '22 07:11

Vivick