0

テンプレートパラメータが行と列のサイズを定義する数独パズルのテンプレートクラスを書いています。C++11 を有効にして g++-4.8 を使用しています。

回避したコンパイルの問題が 1 つありますが、期待どおりに動作しない理由を理解したいと思います。

私の 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' はこのスコープで宣言されていませんでした リターン 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

なぜ私に説明できますか?

4

1 に答える 1

1

問題は、テンプレート引数に依存しない名前が、テンプレート引数が不明な場合にのみ検索されることです。基本クラスはテンプレート引数に依存しているため (テンプレート内にネストされているため暗黙的に)、コンパイラは基本クラスをまだ見ていません: テンプレートがインスタンス化されるまで特殊化され、完全に異なるクラスになる可能性があります。

修正は、ベース メンバーへの参照をテンプレート引数に依存させることthis->virtualLineIdxです。

于 2013-10-05T22:54:20.873 に答える