Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ templates declaration is not visible

Tags:

c++

templates

I have following code:

#include <cstddef>
#include <cstdint>

using ReadIteratorType = Buffer::iterator;
using WriteIteratorType = Buffer::iterator;

template <typename TReadIterator, typename TWriteIterator>
class FieldBase
{
public:
    using ReadIterator = TReadIterator;
    using WriteIterator = TWriteIterator;

    virtual void read(ReadIterator& readIterator, std::size_t& len) = 0;
    virtual void write(WriteIterator& writeIterator, std::size_t& len) = 0;
};

template <typename TValue>
class Field : public FieldBase<ReadIteratorType, WriteIteratorType>
{
public:
    using ValueType = TValue;

    virtual const ValueType& getValue() const { return m_value; };
    virtual void setValue(const ValueType& value) { m_value = value;}
    constexpr std::size_t length() { return sizeof(TValue); }

protected:
    ValueType m_value {};
};

template <typename T>
class IntField : public Field<T>
{
public:

    void read(ReadIterator& readIterator, std::size_t& len) override
    {

    }

    void write(WriteIterator& writeIterator, std::size_t& len) override
    {

    }
};

Whenever I try to compile this particular code I have t

error: ‘ReadIterator’ has not been declared void read(ReadIterator& readIterator, std::size_t& len) override

error: ‘WriteIterator’ has not been declared void write(WriteIterator& writeIterator, std::size_t& len) override

But if I change definition IntField class to class IntField : public Field or whatever that has certain type it compiles properly. Why the IntField can't be template in current context?

like image 402
bielu000 Avatar asked May 14 '19 19:05

bielu000


1 Answers

This is a well-known problem. Compiler doesn't know that ReadIterator needs to come from the templated base class, as it tries to resolve the name during first step of template instantiation. You might find more information on the 2-phase name lookup here: http://blog.llvm.org/2009/12/dreaded-two-phase-name-lookup.html

You need to be verbose here:

void read(typename Field<T>::ReadIterator& readIterator, std::size_t& len) override

Or, to save some typing:

using base_t = Field<T>;
void read(typename base_t::ReadIterator& readIterator, std::size_t& len) override

On a side note, your code doesn't make a huge lot of sense to me. I would expect your IntField to not be a template:

class IntField : public Field<int>
// ...
like image 172
SergeyA Avatar answered Oct 21 '22 16:10

SergeyA