0

ある種のコピー演算子を実装しようとしています。目的は、2つのクラスを持つことです。1つはコンテナーを参照し、もう1つはコンテナーを使用して何かを実行します。また、Browseクラスは(何らかの理由で)出力コンテナのイテレータを維持し、もう1つのクラスはそれを使用してインクリメントを計算できます。

残念ながら、コンパイラはback_insert_iteratorを出力イテレータに変換できないようです。なんで?

#include <iostream>
#include <iterator>
#include <vector>

typedef std::vector<int> Vec;

// An operator that copy an item onto another
template< class TIN, class TOUT >
class DoCopy
{
    TOUT operator()( const typename TIN::iterator i_in, const typename TOUT::iterator i_out )
    {
        const typename TOUT::iterator i_incr = i_out;
        (*i_incr) = (*i_in);
        std::advance( i_incr, 1 );
        return i_incr;
    }
};

// The class that iterate over a container, calling an operator for each item
template< class TIN, class TOUT >
class Browse
{
    public:
        // We keep a reference to the operator that really do the job
        DoCopy<TIN,TOUT> & _do;
        Browse( DoCopy<TIN,TOUT> & op ) : _do(op) {}

        // Iterate over an input container
        TOUT operator()(
                const typename TIN::iterator in_start,
                const typename TIN::iterator in_end,
                const typename TOUT::iterator out_start
            )
        {
            TOUT i_out = out_start;

            for( TIN i_in = in_start; i_in != in_end; ++i_in ) {
                // it is not shown why here, but we DO want the operator to increment i_out
                i_out = _do(i_in, i_out);
            }
        }
};

int main()
{
    // in & out could be the same type or a different one
    Vec in;
    Vec out;
    DoCopy<Vec,Vec> do_copy;
    Browse<Vec,Vec> copy(do_copy);

    std::back_insert_iterator< Vec > insert_back(out);

    // Here, g++ cannot find the corresponding function :
    copy( in.begin(), in.end(), insert_back );

}

g ++は、次のエラーでコンパイルに失敗します。

$ g++ test.cpp && ./a.out
    test.cpp: In function ‘int main()’:
    test.cpp:54:49: erreur: no match for call to ‘(Browse<std::vector<int>, std::vector<int> >) (std::vector<int>::iterator, std::vector<int>::iterator, std::back_insert_iterator<std::vector<int> >&)’
    test.cpp:22:11: note: candidate is:
    test.cpp:30:18: note: TOUT Browse<TIN, TOUT>::operator()(typename TIN::iterator, typename TIN::iterator, typename TOUT::iterator) [with TIN = std::vector<int>, TOUT = std::vector<int>, typename TIN::iterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >, typename TOUT::iterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >]
    test.cpp:30:18: note:   no known conversion for argument 3 from ‘std::back_insert_iterator<std::vector<int> >’ to ‘__gnu_cxx::__normal_iterator<int*, std::vector<int> >’
4

1 に答える 1

2

問題の主な原因は次のとおりです。継承ツリーに直接関係していませんstd::back_insert_iterator< V<T> >std::vector<T>::iterator

  • std::vector<T>::iterator__normal_iterator<T>(他のスーパークラスはありません)(を見てstl_vector.hください)std::vector<T>::iteratorstl_iterator.h__normal_iterator
  • std::back_insert_iterator< V<T> >イテレータです(他のスーパークラスはありません)(stl_iterator.hforstd::back_insert_iteratorstl_iterator_base_types.hforを見てくださいstd::iterator)。

それらはどの方向にも変換できません。

したがって、2番目のテンプレート引数は直接std::back_insert_iteratorまたはである必要がiterator<>あり、最初のパラメーターはそれが出力演算子であることを示します。

によってstd::advance( iterator, 1 )、私はあなたが意味したと思います++iterator。これは、イテレータの次の要素に進むための標準的な方法です。

さらに、アウトイテレータはすべきではありませんconst。そうでない場合、それらは影響を実装しませんoperator=

38行目、はタイプではなくi_in、タイプである必要があります。ブラウズは、出力イテレータも返す必要があります。typename TIN::iteratorTINoperator()

最終的なコードは次のようになります。

#include <iostream>
#include <iterator>
#include <vector>

typedef std::vector<int> Vec;

// An operator that copy an item onto another
template< class TIN, class TOUT >
class DoCopy
{
    public:

    TOUT operator()( const typename TIN::iterator i_in, const TOUT i_out )
    {
        TOUT i_incr = i_out;
        (*i_incr) = (*i_in);
        //std::advance( i_incr, 1 );
        ++i_incr;
        return i_incr;
    }
};

// The class that iterate over a container, calling an operator for each item
template< class TIN, class TOUT >
class Browse
{
    public:
        // We keep a reference to the operator that really do the job
        DoCopy<TIN,TOUT> & _do;
        Browse( DoCopy<TIN,TOUT> & op ) : _do(op) {}

        // Iterate over an input container
        TOUT operator()(
                const typename TIN::iterator in_start,
                const typename TIN::iterator in_end,
                const TOUT out_start
            )
        {
            TOUT i_out = out_start;

            for( typename TIN::iterator i_in = in_start; i_in != in_end; ++i_in ) {
                // it is not shown why here, but we DO want the operator to increment i_out
                i_out = _do(i_in, i_out);
            }
            return i_out;
        }
};

int main()
{
    // in & out could be the same type or a different one
    Vec in;

    in.push_back(1);
    in.push_back(3);
    in.push_back(3);
    in.push_back(7);

    Vec out;
    DoCopy<Vec, std::back_insert_iterator<Vec> > do_copy;
    Browse<Vec, std::back_insert_iterator<Vec> > copy(do_copy);

    std::back_insert_iterator< Vec > insert_back(out);

    // Here, g++ cannot find the corresponding function :
    copy( in.begin(), in.end(), insert_back );

    for( unsigned i = 0, s = out.size(); i < s; ++i )
    {
        std::cout << out[i] << " ";
    }
    std::cout << std::endl;
}

C++エラーをより明確にするclang++に感謝します。

于 2012-09-21T19:16:28.160 に答える