2

I have a Matrix class template which looks like this:

using matrix_size_t = unsigned int;
using matrix_data_t = double;

template <matrix_size_t row, matrix_size_t col>
class Matrix
{
protected:
    matrix_data_t m_matrix[row][col];

//more code irrelevant to the question...
}

I also have a subclass template SquareMatrix that looks like this:

template <matrix_size_t size>
class SquareMatrix :public Matrix<size, size>
{
public:
    matrix_data_t trace()
    {
        matrix_data_t trace{ 0 };
        for (matrix_size_t j{ 0 }; j < size; ++j)
        {
            trace += m_matrix[j][j]; //C3861 error in MVS: m_matrix identifier not found
        }
        return trace;
    }
};

The problem is: I'm not able to access the member m_matrix from the subclass.

When I substitute m_matrix with Matrix<size,size>::m_matrix, the sub-class code works:

template <matrix_size_t size>
class SquareMatrix :public Matrix<size, size>
{
public:
    matrix_data_t trace()
    {
        matrix_data_t trace{ 0 };
        for (matrix_size_t j{ 0 }; j < size; ++j)
        {
            trace += Matrix<size, size>::m_matrix[j][j]; //this works
        }
        return trace;
    }
};

I don't know if this is the right thing to do. Please help me understand what is going on!

Abhishek A Udupa
  • 401
  • 6
  • 13
  • 4
    Please, write `trace += this->m_matrix[j][j];`. Auto-resolution of inherited members doesn't work in template classes. You have to provide an explicit hint from where `m_matrix` does come from. (The scope operator, you used in your 3rd snippet instead is the other alternative.) – Scheff's Cat May 08 '20 at 05:40
  • Gotcha! But, is the usage of scope operator correct? Or does it lead to some UD behavior sometime in the future? – Abhishek A Udupa May 08 '20 at 06:15
  • 1
    _But, is the usage of scope operator correct? Or does it lead to some UD behavior sometime in the future?_ I seriously don't believe that this will break in the future. Templates aside, if you have a class and a derived class where the derived class overloads a member, how do you access the member (with same name) of the base class? ;-) – Scheff's Cat May 08 '20 at 06:17

1 Answers1

2

I don't know if this is the right thing to do.

Yes. You can also use this->m_matrix instead.

m_matrix is a nondependent name, which won't be looked up in the dependent base class Matrix<size, size>, it depends on the template parameter size. Making m_matrix dependent as Matrix<size, size>::m_matrix or this->m_matrix, then the name would be looked up at the time of instantiation, at that time the base class specialization that must be explored will be known.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • So, using either one leads to the same result right? Or is there something else I'm missing...like performance penalty or some future UD behavior...? – Abhishek A Udupa May 08 '20 at 06:18
  • 1
    @AbhishekAUdupa _like performance penalty_ Unlikely. I'm quite sure that every serious C++ compiler should emit the exact same code in both cases. (But you may try yourself in CompilerExplorer.) – Scheff's Cat May 08 '20 at 06:20
  • @AbishekAUdupa As both ways would work for member vars. and functions, I got used to use `this->` for vars. and functions but the scope for types (where `this->` isn't applicable). That provides some "visual effect" additionally as things are a little bit easier to distinguish then. (In the case that something has been overloaded in the derived template class but the overloaded member of base class has to be addressed (like mentioned in my other comment), then, of course, you have to fall back to the scope again.) – Scheff's Cat May 08 '20 at 06:23
  • Now I understand. – Abhishek A Udupa May 08 '20 at 06:50