2010-03-14 3 views
4

У меня возникла проблема с написанием предложения catch для исключения, являющегося классом, вложенным в шаблон. Чтобы быть более точным, у меня есть следующее определение шаблона и исключения:Захват исключения вложенного шаблона [C++]

/** Generic stack implementation. 
    Accepts std::list, std::deque and std::vector 
    as inner container. */ 
template < 
typename T, 
    template < 
     typename Element, 
     typename = std::allocator<Element> 
    > class Container = std::deque 
> 
class stack { 
public: 
    class StackEmptyException { }; 
    ... 

    /** Returns value from the top of the stack. 
     Throws StackEmptyException when the stack is empty. */ 
    T top() const; 
    ... 
} 

У меня есть следующий метод шаблон, который я хочу исключение поймать:

template <typename Stack> 
void testTopThrowsStackEmptyExceptionOnEmptyStack() { 
    Stack stack; 
    std::cout << "Testing top throws StackEmptyException on empty stack..."; 

    try { 
     stack.top(); 
    } catch (Stack::StackEmptyException) { 
     // as expected. 
    } 

    std::cout << "success." << std::endl; 
} 

Когда я скомпилировать его (-Wall , -патентный) Я получаю следующую ошибку:

In function ‘void testTopThrowsStackEmptyExceptionOnEmptyStack()’: 
error: expected type-specifier 
error: expected unqualified-id before ‘)’ token 
=== Build finished: 2 errors, 0 warnings === 

Заранее благодарим за любую помощь!

Что интересно, если реализация стека не была шаблоном, тогда компилятор принимал бы код как есть.

PS. Я также попытался переопределить тип метода шаблона, но я не смог выполнить эту работу.

+1

@Karol, так как вы новичок в SO land: Если вы обнаружили, что ваша проблема решена, вы должны выбрать ответ как «принятый» (щелкните по метке слева до ответа). Поэтому люди могут видеть, что ваша проблема уже решена путем ответа. –

+0

Кстати, вам действительно нужен каждый тип стека, чтобы бросить другой класс исключения? 'stack :: StackEmptyException' и' stack :: StackEmptyException' являются несвязанными типами. Что, если вы захотите поймать его выше в коде, где-нибудь, кто знает, что есть стек, который используется, но не знает (или не должен знать), какой из них? –

+0

Я согласен со Стивом, я обычно не создаю новых исключений, как вложенные классы в классе шаблона. Я предпочитаю создавать базовый класс (например, «BaseStack») для определения моих исключений и иметь каждый шаблонный класс 'Stack ' наследующий от 'BaseStack', таким образом у меня есть возможность перехватывать эти исключения вне кода шаблона без перечисления всех возможные специализированные шаблоны. –

ответ

9

Использование typename:

template <typename Stack> 
void testTopThrowsStackEmptyExceptionOnEmptyStack() { 
    Stack stack; 
    std::cout << "Testing top throws StackEmptyException on empty stack..."; 

    try { 
     stack.top(); 
    } catch (typename Stack::StackEmptyException) { 
     // as expected. 
    } 

    std::cout << "success." << std::endl; 
} 

анализатор компилятора в противном случае предполагается, что Stack::StackEmptyException не тип и misparses код (он не может знать, что это тип, потому что в этот момент он оленья кожа» t знает, какой тип Stack есть, поэтому потенциально StackEmptyException может быть статическим элементом данных аналогичным образом). Вы также должны обычно искать по ссылке вместо значения.

+0

Это работает, спасибо большое! – Karol

+0

Смотрите также шаблоны: http://womble.decadentplace.org.uk/c++/template-faq.html –

+0

Я сделаю это. Благодаря! – Karol

Смежные вопросы