'How can I collapse similar overloaded functions into one function C++?
Suppose I have the following two identical functions but with different arguments and I want to collapse them into one function. How can I do that?
template <typename T>
ostream& operator<<(ostream& os, const set<T>& v) {
os << "{";
char comma[3] = {'\0', ' ', '\0'};
for (const auto& e : v) {
os << comma << e;
comma[0] = ',';
}
return os << "}";
}
template <typename F, typename S>
ostream& operator<<(ostream& os, const map<F, S>& v) {
os << "{";
char comma[3] = {'\0', ' ', '\0'};
for (const auto& e : v) {
os << comma << e;
comma[0] = ',';
}
return os << "}";
}
This is assuming that the operator <<(ostream& os, const pair< K, V > p) is already defined so the map cout << e should work properly.
I want something similar to the following pseudo-code:
template <typename F, typename S, typename X=set or map>
ostream& operator<<(ostream& os, const X<F, S>& v) {
os << "{";
char comma[3] = {'\0', ' ', '\0'};
for (const auto& e : v) {
os << comma << e;
comma[0] = ',';
}
return os << "}";
}
cout << aMap << aSet; // should work!
Solution 1:[1]
You can add this type trait ,which within my research, i havn't found in the stl.
template <typename T, typename = void>
struct is_T_iterable : std::false_type {};
// this gets used only when we can call std::begin() and std::end() on that type
template <typename T>
struct is_T_iterable<T, std::void_t<decltype(std::begin(std::declval<T>())),
decltype(std::end(std::declval<T>()))>> :
std::true_type {};
and you can use this in two ways
C++11 and above:
template<class T>
constexpr is_iterable = is_T_iterable<T>::value;
template <class T>
ostream& operator<<(ostream& os, const T& v) {
static_assert(is_iterable<T>,
"T is not an iterable class");
os << "{";
char comma[3] = {'\0', ' ', '\0'};
for (const auto& e : v) {
os << comma << e;
comma[0] = ',';
}
return os << "}";
}
or in C++20 and above you can use concepts:
template<class T>
concept iterable = is_T_iterable<T>::value;
template <iterable T>
ostream& operator<<(ostream& os, const T& v) {
os << "{";
char comma[3] = {'\0', ' ', '\0'};
for (const auto& e : v) {
os << comma << e;
comma[0] = ',';
}
return os << "}";
}
both these methods are compile time so it will add no overhead. depends on what you find most readable to you.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | MaxCE |
