The C++ code that using templates doesn't compile in c++ 20, but was ok in c++ 17

160 Views Asked by At

I have some legacy code that I want to upgrade to c++20. The code compiles in c++17 without any issues but fails if I switch to C++20. I simplified the code as much as possible, please look at the example. I am using Visual Studio 2022 on Windows



class MyFile
{
public:
    void Read(){ }
};

class ArrayWrapper;

class BaseClass
{
public:
    ArrayWrapper* arrayWrapper;
};

template <class T> class ArrayClass : public BaseClass
{
public:
    void Add()
    {
        arrayWrapper->file.Read();
    }
};


class ArrayWrapper
{
public:
    ArrayWrapper(): file(new MyFile()){ }
    ~ArrayWrapper() { delete file; }
    MyFile* file;
    ArrayClass<int> Array{};
    void Update()
    {
        Array.Add();
    }
};

int main()
{
    ArrayWrapper wrapper;
    wrapper.Update();
}

And this is the error message that I am getting:

error C2027: use of undefined type 'ArrayWrapper'
message : see declaration of 'ArrayWrapper'
message : see reference to class template instantiation 'ArrayClass<T>' being compiled

I did look on the stack overflow and in the C++ docs but couldn't figure out what is wrong with this code in C++ 20 Can someone explain how to fix this issue, please?

1

There are 1 best solutions below

0
Quimby On BEST ANSWER

Move ArrayClass::Add definition after ArrayWrapper.

The method and the whole ArrayClass<int> is instantiated right after the definition of the class template, at which point ArrayWrapper is still not fully defined.

You would get the same error if ArrayClass was not a template.

class MyFile
{
public:
    void Read(){ }
};

class ArrayWrapper;

class BaseClass
{
public:
    ArrayWrapper* arrayWrapper;
};

template <class T> class ArrayClass : public BaseClass
{
public:
    void Add();
};


class ArrayWrapper
{
public:
    ArrayWrapper(): file(new MyFile()){ }
    ~ArrayWrapper() { delete file; }
    MyFile* file;
    ArrayClass<int> Array{};
    void Update()
    {
        Array.Add();
    }
};

template <class T> 
void ArrayClass<T>::Add()
{
    arrayWrapper->file->Read();
}

int main()
{
    ArrayWrapper wrapper;
    wrapper.Update();
}

Also, it should be arrayWrapper->file->Read(); file is a pointer.