Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catching a nested-in-template exception [C++]

I have a problem with writing a catch clause for an exception that is a class nested in a template. To be more specific, I have a following definition of the template and exception:

/** 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;
   ...
}

I have a following template method that I want exception to catch:

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;
}

When I compile it (-Wall, -pedantic) I get the following error:

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

Thanks in advance for any help!

What is interesting, if the stack implementation was not a template, then the compiler would accept the code as it is.

PS. I also tried redefining the template method type, but I couldn't make this work.

like image 359
Karol Avatar asked Jan 23 '23 10:01

Karol


1 Answers

Use 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;
}

The compiler's parser otherwise assumes that Stack::StackEmptyException is not a type and misparses the code (it can't know that it is a type, because at that point it doesn't know what type Stack is, so potentially StackEmptyException could be a static data-member likewise). You should also generally catch by reference instead of by value.

like image 69
Johannes Schaub - litb Avatar answered Jan 28 '23 17:01

Johannes Schaub - litb