оператор перегрузки << для std :: stack - PullRequest
1 голос
/ 15 сентября 2011

Код идет первым:

//. Cpp файл

template <typename T>
ostream &operator<<(ostream &os, stack<T> &st)
{
    while(! st.empty()) {
        os << st.top() << " ";
        st.pop();
    }
    return os;
}

template <typename T>
void stack_sorter(stack<T> &st)
{
    cout << st << endl;  //no output, st is empty?
    //...
}

int main()
{
    stack<int> s;
    s.push(4);
    s.push(3);
    s.push(5);
    cout << s << endl;  //ok
    stack_sorter(s);
}

вывод:

5 3 4  //this was the output in main, not in stack_sorter
       //empty line, but s is not empty, why?

Вопрос:

Как и что я сделалв основном я передаю s в stack_soter (), но я не получаю вывод в stack_sorter ().Что не так?

Ответы [ 4 ]

5 голосов
/ 15 сентября 2011

В вашем operator << вы выводите все значения для их вывода.Таким образом, после cout << s << endl; ваш стек очищается!

Одна из возможностей - не передавать по ссылке, а копировать стек.Тем не менее, это также скопирует все объекты в нем.

3 голосов
/ 15 сентября 2011
template <typename T>
ostream &operator<<(ostream &os, stack<T> st) //not &st
{
    while(! st.empty()) {
        os << st.top() << " ";
        st.pop();
}
return os;
}
2 голосов
/ 15 сентября 2011

Как уже отмечали другие, pop_back делает вашу выходную операцию разрушительной.Просто невозможно прочитать содержимое стека, не опустошив его… Такова природа чистого стека.

Кроме того, перегрузка операторов для стандартных типов очень плохая практика.Из-за того, как работает поиск имени (то есть, как язык находит функцию перегрузки для вызова), предполагается, что функции перегрузки находятся в том же пространстве имен, что и типы, для которых они перегружаются.Поскольку вы не можете поместить функцию в std::, следующая лучшая альтернатива - это глобальное пространство имен, которое затем загрязняет это.

Но проблема решаема!К счастью, stack предусматривает наследование.Базовый контейнер доступен для производных классов и называется c.

template< typename value_arg, typename container_arg = std::deque< value_arg > >
struct printable_stack : std::stack< value_arg, container_arg > {

    // provide constructors :v( . This is better supported in C++11.
    printable_stack( container_arg const &in = container_arg() )
        : std::stack< value_arg, container_arg >( in ) {}

    friend std::ostream &operator<<
                            ( std::ostream &s, printable_stack const &o ) {
        for ( typename container_arg::iterator i = this->c.begin();
                                               i != this->c.end(); ++ i ) {
            s << * i << ' ';
        }
    }
};

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

1 голос
/ 15 сентября 2011

Ваш вызов st.pop() в цикле в ostream &operator<<(ostream &os, stack<T> &st) очищает стек.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...