Ошибка при выводе вектора векторов при шаблонных функциях
У меня есть шаблонные функции, выводящие векторы и множества:
#include <iostream>
#include <vector>
#include <set>
using namespace std;
template <typename Container>
std::ostream& Print(ostream& out, const Container& container) {
bool isnt_first = false;
for (const auto& element : container) {
if (isnt_first) {
out << ", " << element;
}
else {
isnt_first = true;
out << element;
}
}
return out;
}
template <typename Element>
ostream& operator<<(ostream& out, const set<Element>& container) {
out << "{";
Print(out, container);
out << "}";
return out;
}
template <typename Element>
ostream& operator<<(ostream& out, const vector<Element>& container) {
out << "[";
Print(out, container);
out << "]";
return out;
}
int main() {
setlocale(LC_ALL, "ru");
const set<string> cats = { "Мурка"s, "Белка"s, "Георгий"s, "Рюрик"s };
cout << cats << endl;
const vector<int> ages = { 10, 5, 2, 12 };
cout << ages << endl;
const vector<vector<string>> a = {
{ "Мурка"s, "Белка"s, "Георгий"s, "Рюрик"s },
{ "Мурка"s, "Белка"s, "Георгий"s, "Рюрик"s },
{ "Мурка"s, "Белка"s, "Георгий"s, "Рюрик"s }
};
cout << a << endl;
return 0;
}
Но если я пытаюсь вывести вектор векторов, то компилятор выдает ошибку:
бинарный "<<": не найден оператор, принимающий правый операнд типа "const std::vector<std::string,std::allocator<std::string>>" (или приемлемое преобразование отсутствует)
Как это исправить? Я слышал, что функции должны рекурсивно печатать векторы векторов, но у меня так и не вышло это сделать
Ответы (1 шт):
Ну, раз надо играть в рамках вашего ответа — без проблем, исправить ваш очень легко — просто поясните компилятору, что такие операторы есть. Проще (вернее, короче), впрочем, пояснить операторам наличие функции Print:
template <typename Container>
std::ostream& Print(ostream& out, const Container& container);
template <typename Element>
ostream& operator<<(ostream& out, const set<Element>& container) {
out << "{";
Print(out, container);
out << "}";
return out;
}
template <typename Element>
ostream& operator<<(ostream& out, const vector<Element>& container) {
out << "[";
Print(out, container);
out << "]";
return out;
}
template <typename Container>
std::ostream& Print(ostream& out, const Container& container) {
bool isnt_first = false;
for (const auto& element : container) {
if (isnt_first) {
out << ", ";
}
else {
isnt_first = true;
}
out << element;
}
return out;
}
У вас же Print ничего не знает о том, что оператор для вектора есть, потому что он объявлен уже после функции Print.
P.S. Можно, кстати, и мой вариант дописать под ваши требования (писал в спешке, Новый год на носу :), так что явно можно сделать и куда качественнее, кто исправит — не возражаю ни капли).
template<template <typename> class Container, typename T>
const char * pars(const Container<T>&)
{
return " ";
}
template<typename T>
const char * pars(const set<T>&)
{
return "{}";
}
template<typename T>
const char * pars(const vector<T>&)
{
return "[]";
}
template <typename Container, typename = enable_if_t<!is_same_v<Container,string>>>
ostream& operator<<(ostream& out, const Container& container)
{
const char * p = pars(container);
out << string(1,p[0]);
bool isnt_first = false;
for (const auto& element : container)
{
if (isnt_first) {
out << ", "s;
}
else {
isnt_first = true;
}
out << element;
}
out << string(1,p[1]);
return out;
}
main остается все та же.