В программе есть множество всяких множеств , мне необходимо инода
выводить их значения на консоль. Написал простую шаблонную функцию:
template<class T>
std::ostream&
operator<<(std::ostream& st, std::set<T> const& s)
{
st << '{';
for(typename std::set<T>::const_iterator i = s.begin();
i != s.end();
++i)
{
st << " " << (*i);
}
st << '}';
return st;
}
Теперь можно делать так:
set<int> si;
set<string> ss;
cout << si << ss;
// Всё работает просто на ура!
set<myClass> smc;
cout << smc;
// Работает, если для myClass определён operator<<
Недавно потребовалось хранить в множествах итераторы других контейнеров.
И вот
тут появились проблемы:
typedef vector<myclass> seq_t;
typedef seq_t::const_iterator iter_t;
typedef set<iter_t> set_of_iter_t;
// Пытаюсь вывести
set_of_iter_t s;
cout << s;
// Правильно, компилятор говорит, что operator << не определен для iter_t
Так вот, вопрос: как написать шаблонную функцию для итераторов?
А вот с оператором >> будут проблемы, так как параметр шаблона надо указывать явно,
потому что вывести параметр шаблона из таких конструкций, (когда параметр шаблона в квалификаторе) невозможно.
std::vector<T>::const_iterator i
Re: Шаблонная функция для итераторов шаблонных контейнеров
Здравствуйте, Abulafia, Вы писали:
A> Так вот, вопрос: как написать шаблонную функцию для итераторов?
Лови
// функция для вывода элементов-итераторовtemplate<typename T>
void out(std::ostream& stream, const T& v, boost::mpl::int_<sizeof(bool)>)
{
stream << " " << *v;
}
// функция для вывода обычных элементовtemplate<typename T>
void out(std::ostream& stream, const T& v, boost::mpl::int_<sizeof(int)>)
{
stream << " " << v;
}
// SFINAE-based определение, является ли элемент контейнера итераторомtemplate<typename Type>
bool fff(Type*, typename Type::iterator_category* = 0, typename Type::value_type* = 0, typename Type::difference_type* = 0, typename Type::pointer* = 0);
int fff(...);
template<class T>
std::ostream& operator << (std::ostream& stream, std::set<T> const& s)
{
BOOST_STATIC_ASSERT(( sizeof(int) != sizeof(bool) ));
stream << '{';
for (typename std::set<T>::const_iterator i = s.begin(); i != s.end(); ++i)
out(stream, *i, boost::mpl::int_<sizeof(fff(&*i))>());
stream << '}';
return stream;
}
Решение было сделано на скорую руку, поэтому надо доработать напильником. Но тем не менее сейчас решение рабочее для итераторов стандартной библиотеки.
Сейчас не работает для указателей, не работает для итераторов на итератор
Да, забыл добавить, если у твоего типа есть typedef'ы iterator_category, value_type, difference_type, pointer, то он будет распознаваться как итератор.
Можно так же проверять на наличие типа reference и на наследование от типа std::iterator, но там есть некоторые технические проблемы — надо думать...