base: Apply the stl_helpers helper judiciously.

The existing template would apply the helper operator to *any* template
which took two types, regardless of what that template was. The
assumption was that those types *must* be STL containers, because no
other template takes two types, right?

Instead, this new version uses type traits to explicitly whitelist types
which the helper applies to. Currently the only type it seems to be used
with is std::vector, but by defining more specializations of
IsHelpedContainer, other types/templates can be enabled as well.

This is particularly important when moving to c++17, since the
std::string class would then apparently match the old overload. That
makes the << operator ambiguous and breaks the build.

Change-Id: Id283746a2ccced8882fa23e6f9e69fe22e206b70
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/45901
Reviewed-by: Gabe Black <gabe.black@gmail.com>
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Gabe Black
2021-05-23 00:56:45 -07:00
parent b783a62fb8
commit ed0a56c185

View File

@@ -31,29 +31,38 @@
#include <algorithm>
#include <iostream>
#include <type_traits>
#include <vector>
namespace m5 {
namespace stl_helpers {
template <typename T, typename Enabled=void>
struct IsHelpedContainer : public std::false_type {};
template <typename ...Types>
struct IsHelpedContainer<std::vector<Types...>> : public std::true_type {};
/**
* Write out all elements in an stl container as a space separated
* list enclosed in square brackets
*
* @ingroup api_base_utils
*/
template <template <typename T, typename A> class C, typename T, typename A>
std::ostream &
operator<<(std::ostream& out, const C<T,A> &vec)
template <typename T>
std::enable_if_t<IsHelpedContainer<T>::value, std::ostream &>
operator<<(std::ostream& out, const T &t)
{
out << "[ ";
bool first = true;
auto printer = [&first, &out](const T &elem) {
auto printer = [&first, &out](const auto &elem) {
if (first)
out << elem;
else
out << " " << elem;
};
std::for_each(vec.begin(), vec.end(), printer);
std::for_each(t.begin(), t.end(), printer);
out << " ]";
out << std::flush;
return out;