Как я мог распечатать содержание какого-либо контейнера универсальным способом?

Python появляется связанный компилятором Python, записанным в Python. Вы видите исходный код, и он включает все фазы, от парсинга, абстрактного синтаксического дерева, испускание кода, и т.д. Взломайте его.

9
задан AraK 20 July 2009 в 16:29
поделиться

6 ответов

Вы можете ограничить использование оператора << только для шаблонных контейнеров, указав, что параметр шаблона контейнера сам является шаблоном. Поскольку в контейнерах 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;
}
7
ответ дан 4 December 2019 в 11:43
поделиться

Ваш вновь определенный оператор << выполняет не только для контейнеров, но и для любых других типов, таких как целые числа и строки. Вот почему компилятор жалуется на двусмысленность, когда ему нужно найти соответствующий 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);
}
4
ответ дан 4 December 2019 в 11:43
поделиться

В чем ошибка? Я видел одно, вам нужно имя типа:

typename Container::iterator beg = container.begin();

Здесь происходит то, что компилятор ничего не знает о контейнере, когда он впервые его читает. Поэтому мы должны немного помочь ему и сказать, что итератор будет типом (синтаксически это может быть любое допустимое имя в области класса, то есть функция, переменная, ...). При написании метода шаблона любой тип, который зависит от типа шаблона, должен указывать, что это тип с ключевым словом typename .

3
ответ дан 4 December 2019 в 11:43
поделиться

Ваш оператор вносит свою неоднозначность - он сам может использоваться для печати того, что он пытается напечатать. Мой совет:

  • используйте именованную функцию, не оператор
  • передает контейнер по константной ссылке (однако это не имеет отношения к проблеме)
2
ответ дан 4 December 2019 в 11:43
поделиться

Хорошо, теперь ваш шаблон вызывает путаницу. Компилятор не может выбрать между вашим оператором и тем, который вы ожидаете.

1
ответ дан 4 December 2019 в 11:43
поделиться

Возможно, не такой общий, как то, что вы публикуете (вам необходимо передать тип содержится), а также оставляет дополнительный разделитель в конце, но для этого можно использовать 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]

Обратите внимание, что дополнительный разделитель находится в конце последовательности и что между [и первым элементом нет начального пробела.

1
ответ дан 4 December 2019 в 11:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: