Я создаю класс, представляющий собой набор стеков. Я хочу использовать итератор, чтобы получить элемент в конце и получить доступ к его функциям. Но я получаю следующую ошибку
setOfStacks.cpp:40:6: error: expected ';' after expression
set< stack<Type> >::iterator it = mSetOfStacks.end();
^
;
Класс работает с шаблоном и объявляется следующим образом:
template<typename Type>
class SetOfStacks
{
public:
SetOfStacks(int capacityPerStack);
void push(Type object);
Type pop();
bool isEmpty();
private:
void createNewStackWithElem(Type object);
private:
int mStackCapacity;
set<stack<Type> > mSetOfStacks;
};
Затем в моей функции вставки я пытаюсь получить стек в конце
set< stack<Type> >::iterator it = mSetOfStacks.end();
if( *it->size() < mStackCapacity )
*it->push(object);
где я получаю ошибку при попытке объявить итератор setOfStacks.cpp: 40: 6: error: expected ';' после выражения
также, я попробовал
set<stack<Type> >::iterator it = mSetOfStacks.end();
но это не сработало
Вся функция push
template<typename Type>
void SetOfStacks<Type>::push(Type object) {
// if entire set is empty make a new stack
if( mSetOfStacks.empty() ) {
stack<Type> newStack;
newStack.push(object);
mSetOfStacks.insert(newStack);
}
else {
// check if current stack within limits
set< stack<Type> >::iterator it = mSetOfStacks.end();
if( *it->size() < mStackCapacity )
*it->push(object);
else {
// duplicate code, make another function
stack<Type> newStack;
newStack.push(object);
mSetOfStacks.insert(newStack);
}
}
}
Внутри шаблона функции вложенный iterator
имен является зависимым именем, которое считается объектом, а не типом. Вы хотите указать, что iterator
является типом, используя ключевое слово typename
:
typename std::set<std::stack<Type> >::iterator it = mSetOfStacks.end();
// ^-- here
Шаблоны анализируются в два этапа: на первом этапе код анализируется для его логических компонентов без каких-либо знаний о аргументах или объектах шаблона в зависимости от аргументов шаблона. Если есть вложенное имя в зависимости от аргумента шаблона, компилятор предполагает, что это имя является объектом, а не типом, если вы явно не укажете, что это тип, используя ключевое слово typename
.
code typename set< stack<Type> >::iterator it = mSetOfStacks.end(); --it; if( it->size() < mStackCapacity ) { it->push(object); } else {
вставляемого code typename set< stack<Type> >::iterator it = mSetOfStacks.end(); --it; if( it->size() < mStackCapacity ) { it->push(object); } else {
функции code typename set< stack<Type> >::iterator it = mSetOfStacks.end(); --it; if( it->size() < mStackCapacity ) { it->push(object); } else {
функция-член 'push' недопустима: аргумент 'this' имеет тип 'const std :: stack <int, std :: deque <int, std :: allocator <int>>>', но функция не помечена как const IT-> толчок (объект);
std::set<...>
! Это испортило бы его внутренние инварианты. Кажется, вы хотите что-то вроде std::list<...>
.
auto
- идеальное ключевое слово для этого:
auto it = mSetOfStacks.end();
При использовании С++ 11 вам не нужно указывать тип итератора для определения итератора при инициализации его из-за чего-то вроде mSetOfStacks.end()
. Вместо этого вы можете использовать auto
:
auto it = mSetOfStacks.end();
Кроме того, вы не должны обращаться к этому итератору, так как он указывает один элемент за конец. Если вы хотите, чтобы последний элемент в наборе, уменьшите итератор до его доступа:
--it;
// then use *it
или ссылаться на последний набор с помощью ссылочной переменной:
auto & lastSet = *(--it);
// then use lastSet instead of *it
Если ваш компилятор не поддерживает auto
использование, используйте решение Dietmar.