【问题标题】:Compiling issues when deriving from a class nested in a template [duplicate]从嵌套在模板中的类派生时的编译问题[重复]
【发布时间】:2013-10-05 22:26:36
【问题描述】:

我正在为数独游戏编写模板类,其中模板参数定义了行和列的大小。我正在使用启用 C++11 的 g++-4.8。

我遇到了一个编译问题,但我想了解为什么它没有按预期工作:

我的 RowIteratorImpl 类派生自 VirtualLineIteratorImpl,但我无法访问它的字段 virtualLineIdx 和 cellInVirtualLineIdx,尽管这应该是可能的:

    class VirtualLineIteratorImpl : public CellIteratorImpl
    {
    protected:
        size_t virtualLineIdx;
        size_t cellInVirtualLineIdx;

    public:
        VirtualLineIteratorImpl(size_t virtualLineIdx)
            : virtualLineIdx(virtualLineIdx), cellInVirtualLineIdx(0)
        {}

        virtual void increment(size_t offset)
        {
            virtualLineIdx += offset;
        }
    };

    class RowIteratorImpl : public VirtualLineIteratorImpl
    {
    public:
        using VirtualLineIteratorImpl::VirtualLineIteratorImpl;

        virtual size_t getCellIdx() const 
        {
            // TODO: does not compile
            // return mivTSudoku::getCellIdxInRow(virtualLineIdx, cellInVirtualLineIdx);
            return mivTSudoku::getCellIdxInRow(VirtualLineIteratorImpl::virtualLineIdx, VirtualLineIteratorImpl::cellInVirtualLineIdx);
        }
    };

编译器生成以下消息:

mivSudoku.h:在成员函数‘virtual size_t mivTSudoku::RowIteratorImpl::getCellIdx() const’中: mivSudoku.h:85:39: 错误: 'virtualLineIdx' 未在此范围内声明 return mivTSudoku::getCellIdxInRow(virtualLineIdx, cellInVirtualLineIdx);

这是整个类的定义:

#ifndef MIVSUDOKU_H
#define MIVSUDOKU_H

#include <bitset>
#include <iterator>
#include <memory>

template<size_t n, size_t m=n>
class mivTSudoku
{
public:
    class Cell
    {};

    static constexpr size_t getCellIdx(size_t rowIdx, size_t colIdx) 
    {
        return rowIdx * dim + colIdx;
    }
    static constexpr size_t getCellIdxInRow(size_t rowIdx, size_t cellInRowIdx) 
    {
        return getCellIdx(rowIdx, cellInRowIdx);
    }
    static constexpr size_t getCellIdxInColumn(size_t columnIdx, size_t cellInColumnIdx) 
    {
        return getCellIdx(cellInColumnIdx, columnIdx); 
    }
    static constexpr size_t getCellIdxInBlock(size_t blockIdx, size_t cellInBlockIdx) 
    {
        return getCellIdx((blockIdx / n) * n + (cellInBlockIdx / m), (blockIdx % n) * m + (cellInBlockIdx % m)); 
    }

    class CellIteratorImpl
    {
    public:
        virtual CellIteratorImpl* clone() = 0;
        virtual void increment(size_t) = 0;
        virtual void getCellIdx() const = 0;
    };

    class AllCellIteratorImpl : public CellIteratorImpl
    {
    private:
        size_t m_cellIdx;

    public:
        AllCellIteratorImpl()
            : m_cellIdx(0)
        {}

        virtual void increment(size_t offset)
        {
            m_cellIdx += offset;
        }
        virtual void getCellIdx() const 
        {
            return m_cellIdx;
        }
    };

    class VirtualLineIteratorImpl : public CellIteratorImpl
    {
    protected:
        size_t virtualLineIdx;
        size_t cellInVirtualLineIdx;

    public:
        VirtualLineIteratorImpl(size_t virtualLineIdx)
            : virtualLineIdx(virtualLineIdx), cellInVirtualLineIdx(0)
        {}

        virtual void increment(size_t offset)
        {
            virtualLineIdx += offset;
        }
    };

    class RowIteratorImpl : public VirtualLineIteratorImpl
    {
    public:
        using VirtualLineIteratorImpl::VirtualLineIteratorImpl;

        virtual size_t getCellIdx() const 
        {
            // TODO: does not compile
            //return mivTSudoku::getCellIdxInRow(virtualLineIdx, cellInVirtualLineIdx);
            return mivTSudoku::getCellIdxInRow(VirtualLineIteratorImpl::virtualLineIdx, VirtualLineIteratorImpl::cellInVirtualLineIdx);
        }
    };

    typedef std::bidirectional_iterator_tag CellIterator_tag;
    typedef std::iterator<CellIterator_tag, Cell> CellIteratorBase; 
    class Cellterator : public CellIteratorBase
    {
    private:
        typedef CellIteratorBase baseclass;

    protected:
        mivTSudoku* pSudoku;
        CellIteratorImpl* m_pIterImpl;

    public:
        Cellterator(mivTSudoku* pSudoku, CellIteratorImpl* impl) noexcept
            : pSudoku(pSudoku), m_pIterImpl(impl)
        {
        }

        ~Cellterator()
        {
            delete m_pIterImpl;
            m_pIterImpl = nullptr;
        }

        Cellterator(const Cellterator& rhs) noexcept 
            : pSudoku(pSudoku), m_pIterImpl(rhs.m_pIterImpl->clone())
        {}

        Cellterator(Cellterator&& rhs) noexcept
            : pSudoku(pSudoku), m_pIterImpl(rhs.m_pIterImpl)
        {
            rhs.m_pIterImpl = nullptr;
        }

        Cellterator& operator=(const Cellterator& rhs) noexcept
        {
            if (this == &rhs) return *this;
            this->pSudoku = rhs.pSudoku;
            this->m_pIterImpl = rhs.m_pIterImpl->clone();
        }

        Cellterator& operator=(Cellterator&& rhs) noexcept
        {
            if (this == &rhs) return *this;
            this->pSudoku = rhs.pSudoku;
            this->m_pIterImpl = rhs.m_pIterImpl;
            rhs.m_pIterImpl = 0;
        }

        size_t getCellIdx() const 
        {
            return m_pIterImpl->getCellIdx();
        }

        typedef typename baseclass::reference reference;
        reference operator*()
        {
            return pSudoku->m_field[getCellIdx()];
        }

        reference const operator*() const
        {
            return pSudoku->m_field[getCellIdx()];
        }

        typedef typename baseclass::pointer pointer;
        pointer operator->()
        {
            return pSudoku->m_field + getCellIdx();
        }

        pointer const operator->() const
        {
            return pSudoku->m_field + getCellIdx();
        }

        Cellterator& operator++()
        {
            m_pIterImpl->increment(1);
            return *this;
        }
        Cellterator operator++(int)
        {
            Cellterator iter;
            this->operator++();
            return iter;
        }       
        bool operator==(const Cellterator& rhs) const
        {
            return getCellIdx()==rhs.getCellIdx();
        }
        bool operator!=(const Cellterator& rhs) const
        {
            return !operator==(rhs);
        }
    };

public:
    static const size_t dim = n*m;
    static const size_t ncells = dim*dim;

private:
    Cell m_field[dim];
};


typedef mivTSudoku<3,3> mivSudoku;



#endif // MIVSUDOKU_H

有人能解释一下为什么吗?

【问题讨论】:

  • 以下问题有帮助吗? stackoverflow.com/questions/7908248/…
  • 一个建议:不要使用制表符来缩进markdown中的代码,使用4个空格
  • 好的,非常感谢。使用 this->pointer 解决了这个问题。我现在将抽出时间阅读并完全理解所有内容。非常有用的帖子。

标签: c++ templates c++11 g++ g++4.8


【解决方案1】:

问题是不依赖于模板参数的名称只有在模板参数未知时才会被查找。由于您的基类依赖于模板参数(隐式嵌套在模板中),因此编译器不会查看基类,但是:在模板被实例化之前,它可能会被专门化,从而产生一个完全不同的类。

解决方法是使对基成员的引用依赖于模板参数,例如,通过使用this-&gt;virtualLineIdx

【讨论】:

  • 谢谢。如果您想获得更详细的答案,请查看link nosid 的捐赠。
猜你喜欢
  • 1970-01-01
  • 2014-03-05
  • 1970-01-01
  • 1970-01-01
  • 2016-11-08
  • 2022-01-19
  • 1970-01-01
  • 2021-11-22
相关资源
最近更新 更多