Вы можете использовать специализацию шаблона:
template <typename T> void send(const T&);
namespace detail {
template <typename T> struct Send; // primary template
template <typename T> struct Send<std::vector<T>> { // specialization for vector
static void send(const std::vector<T>& v) {
for (const auto e : v) ::send(e);
}
};
template <typename T, typename U> struct Send<std::pair<T, U>> { // for pair
static void send(const std::pair<T, U>& p) {
::send(p.first); ::send(p.second);
}
};
template <> struct Send<int> { // for int
static void send(int i) { std::cout << i; }
};
}
template <typename T> void send(const T& arg) { detail::Send<T>::send(arg); }
int main() {
int i = 0;
std::vector<int> vi = { 1, 2, 3 };
std::pair<int, int> pi = { 4, 5 };
std::vector<std::pair<int, int>> vpi = { { 7, 8 }, { 9, 0 } };
send(i);
send(vi);
send(pi);
send(vpi);
}
Демонстрационная версия: https://wandbox.org/permlink/cQNpsgSFYmiurqRT
Обратите внимание, что это решение требует специализаций для всех типов контейнеров, которые вы хотите поддерживать (отличается отчто использует эту реализацию для любого типа, который вложил value_type
и size_type
).
Или вы также можете использовать SFINAE:
template <typename T> struct is_vector : std::false_type { };
template <typename T> struct is_vector<std::vector<T>> : std::true_type { };
template <typename T> struct is_pair : std::false_type { };
template <typename T, typename U> struct is_pair<std::pair<T, U>> : std::true_type { };
template <typename T> void send(T i, std::enable_if_t<std::is_integral_v<T>, int> = 0) {
std::cout << i;
}
template <typename T> void send(const T& p, std::enable_if_t<is_pair<T>::value, int> = 0) {
send(p.first); send(p.second);
}
template <typename T> void send(const T& v, std::enable_if_t<is_vector<T>::value, int> = 0) {
for (const auto & e : v) send(e);
}
... // same main
Кроме того, вы также можете проверить наличие типов элементов следующим образом:
template <typename T> struct has_value_type {
using yes = char[1]; using no = char[2];
template <typename C> static constexpr yes& test(typename C::value_type*);
template <typename> static constexpr no& test(...);
static constexpr bool value = sizeof(test<T>(nullptr)) == sizeof(yes);
};
... // similarly: has_size_type, has_first_type, and has_second_type
template <typename T> void send(T i, std::enable_if_t<std::is_integral_v<T>, int> = 0) {
std::cout << i;
}
template <typename T> void send(const T& p, std::enable_if_t<has_first_type<T>::value && has_second_type<T>::value, int> = 0) {
send(p.first); send(p.second);
}
template <typename T> void send(const T& v, std::enable_if_t<has_value_type<T>::value && has_size_type<T>::value, int> = 0) {
for (const auto & e : v) send(e);
}
... // same main
Демонстрационная версия: https://wandbox.org/permlink/qD7vp2ebzFaR15qf