How would you go about writing a library that, when included, it overloads the <<
operator for any* existing STL container?
The one self-imposed requirement is that it mustn't include any of the containers' header files. That would bloat the final executable unnecessarily. It makes more sense to include this header after the containers' that I would like to work with. This restriction implies the use of templates
or macros
.
I'm looking for advice and pointers, so, please, don't just post fully working code that can do this! Implementing this myself is part of the learning process. Small snippets of code that demonstrate how certain things work are welcome.
What I did up to this point:
I have overloaded the <<
operator for every container with a different template signature. The problem that I have run into with this approach is, that there are containers that have the same number of template parameters, but some contain std::pair
-s, others single values
. More precisely, this is the case of std::map
& std::multimap
vs std::unordered_set
& std::unordered_multiset
.
This collision forces me to either implement a non-template version of one of the pairs, or to come up with a way to differentiate between std::pair
-s and single values
. I don't really know how to go about doing the second one, though. The reason because I'm not "how to do that" directly is that I'm starting to believe that this could be avoided entirely with a better overall design.
Thank you in advance!
What worked for me:
operator<<
for std::pair
operator<<
for every STL container with different template arguments
Note:
template <typename T1>
andtemplate <typename T1, typename T2>
are differenttemplate <typename T1, typename T2>
andtemplate <typename T1, size_t T2>
are differenttemplate <typename T1, typename T2>
andtemplate <typename C1, typename C2>
are NOT different
Use "templates in templates", so for example a function would look like:
template <typename Type, template <typename TYPE> class TClass>
void func(TClass<Type>& tc) {
if (tc.somethingTrue())
tc.doStuff();
}
The SGI implementation of STL is thread-safe only in the sense that simultaneous accesses to distinct containers are safe, and simultaneous read accesses to to shared containers are safe.
The priority_queue :: value_type method is a builtin function in C++ STL which represents the type of object stored as an element in a priority_queue. It acts as a synonym for the template parameter.
You could overload operator<<
as a template that takes a template template argument (i.e., any container).
Then you could provide two overloads of a template function (e.g., print
) that the one overload would specialize on std::pair
.
template<typename T>
std::ostream& print(std::ostream &out, T const &val) {
return (out << val << " ");
}
template<typename T1, typename T2>
std::ostream& print(std::ostream &out, std::pair<T1, T2> const &val) {
return (out << "{" << val.first << " " << val.second << "} ");
}
template<template<typename, typename...> class TT, typename... Args>
std::ostream& operator<<(std::ostream &out, TT<Args...> const &cont) {
for(auto&& elem : cont) print(out, elem);
return out;
}
LIVE DEMO
A very simple attempt at this problem is something like:
template<typename T>
void print_container(std::ostream& os, const T& container, const std::string& delimiter)
{
std::copy(std::begin(container),
std::end(container),
std::ostream_iterator<typename T::value_type>(os, delimiter.c_str()));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With