Python появляется связанный компилятором Python, записанным в Python. Вы видите исходный код, и он включает все фазы, от парсинга, абстрактного синтаксического дерева, испускание кода, и т.д. Взломайте его.
Вы можете ограничить использование оператора << только для шаблонных контейнеров, указав, что параметр шаблона контейнера сам является шаблоном. Поскольку в контейнерах std C ++ также есть параметр шаблона распределителя, вы также должны включить его в качестве параметра шаблона контейнера.
template
< typename T
, template<typename ELEM, typename ALLOC=std::allocator<ELEM> > class Container
>
std::ostream& operator<< (std::ostream& o, const Container<T>& container)
{
typename Container<T>::const_iterator beg = container.begin();
o << "["; // 1
while(beg != container.end())
{
o << " " << *beg++; // 2
}
o << " ]"; // 3
return o;
}
int main()
{
std::vector<int> list;
list.push_back(0);
list.push_back(0);
std::cout << list;
return 0;
}
Ваш вновь определенный оператор <<
выполняет не только для контейнеров, но и для любых других типов, таких как целые числа и строки. Вот почему компилятор жалуется на двусмысленность, когда ему нужно найти соответствующий operator <<
для вывода "["
.
Одним из способов решения этой проблемы было бы переименование вашего функция вывода:
template <class Container>
std::ostream& container_out(std::ostream& o, const Container &container) {
// ...
}
Затем вы можете добавить простые оболочки, чтобы включить operator <<
для всех контейнеров, которые вы хотите распечатать:
template<typename T>
std::ostream& operator<<(std::ostream& o, const std::vector<T> &container) {
return container_out(o, container);
}
template<typename T>
std::ostream& operator<<(std::ostream& o, const std::map<T> &container) {
return container_out(o, container);
}
В чем ошибка? Я видел одно, вам нужно имя типа:
typename Container::iterator beg = container.begin();
Здесь происходит то, что компилятор ничего не знает о контейнере, когда он впервые его читает. Поэтому мы должны немного помочь ему и сказать, что итератор будет типом (синтаксически это может быть любое допустимое имя в области класса, то есть функция, переменная, ...). При написании метода шаблона любой тип, который зависит от типа шаблона, должен указывать, что это тип с ключевым словом typename
.
Ваш оператор вносит свою неоднозначность - он сам может использоваться для печати того, что он пытается напечатать. Мой совет:
Хорошо, теперь ваш шаблон вызывает путаницу. Компилятор не может выбрать между вашим оператором и тем, который вы ожидаете.
Возможно, не такой общий, как то, что вы публикуете (вам необходимо передать тип содержится), а также оставляет дополнительный разделитель в конце, но для этого можно использовать STL:
std::vector<int> v;
v.push_back( 10 );
v.push_back( 20 );
std::cout << "[";
std::copy( v.begin(), v.end(), std::ostream_iterator<int>( std::cout, " " ) );
std::cout << "]";
Будет выводить:
[10 20]
Обратите внимание, что дополнительный разделитель находится в конце последовательности и что между [и первым элементом нет начального пробела.