c++templatesthrow

exception throw: dependent-name is parsed as a non-type, but instantiation yields a type


I have a template Matrix class:

template <typename T, int row, int col>
class Matrix{};

Inside the class decleration I wrote an execption class, based on std::exception:

class MatrixException: public std::exception
{
private:
    const char* errmsg;
public:
    MatrixException(const char* msg="")
        :errmsg(msg) {} 
    const char* what() const noexcept {return errmsg;}
};

class IllegalOperation: public MatrixException
{
    public:
        IllegalOperation(const char* msg="")
            : MatrixException(msg) {}
};

I tried to use it on one of the non-class' functions, in the implantation part, like this:


template <typename T, int row1, int col1, int row2, int col2>
Matrix<T, row1, col2> operator*(const Matrix<T, row1, col1>& mat1, const Matrix<T, row2, col2>& mat2)
{
    if (condition)
        throw Matrix<T, row2, col2>::IllegalOperation("message");
    // do stuff
    return res;
}

I got a warning:

In instantiation of 'Matrix<T, row1, col2> operator*(const Matrix<T, row, col>&, const Matrix<T, row2, col2>&) [with T = int; int row1 = 3; int col1 = 3; int row2 = 3; int col2 = 2]': required from here

And this error message:

dependent-name 'Matrix<T, row, col>::IllegalOperation' is parsed as a non-type, but instantiation yields a type

How can I fix this?

I've looked here: Where and why do I have to put the "template" and "typename" keywords? and then tried to add the word template here and there, but it didn't work.


Solution

  • You should add typename keyword to the throw expression.

     if (condition)
            throw typename Matrix<T, row2, col2>::IllegalOperation("message");
        // do stuff
    

    As stated here

    In a declaration or a definition of a template, including alias template, a name that is not a member of the current instantiation and is dependent on a template parameter is not considered to be a type unless the keyword typename is used or unless it was already established as a type name, e.g. with a typedef declaration or by being used to name a base class.

    Hence IllegalOperation in this case is not considered to by a type, but rather is considered probably as a function.