私がやろうとしているのは、ForwardIterator(またはbeginとendのイテレーターのペア)を返すことです。これにより、元の実装をクライアントクラスから隠しておくことができます。そのような例は見つかりませんでした。
基礎となる実装がvectorの場合、イテレータはvector :: iteratorです。出力をテンプレート化しても、これは機能しないようです。
オブジェクトをそのまま返すことと、呼び出し元がその型を知らないことを同時に期待することはできません。オブジェクトの実際の型を「隠す」一般的な方法は、インターフェイスの背後に隠すことです。
たとえば、次のように書きたい場合があります。
template<typename T>
class Cursor
{
public:
typedef T value_type;
virtual ~Cursor () {}
virtual bool has_result () = 0;
virtual value_type get_result () = 0;
};
// implements cursor interface for any sequence
// described as a pair of forward iterators.
template<typename I>
class ForwardSequenceCursor :
public Cursor<std::iterator_traits<I>::value_type>
{
I myCurrent;
const I myEnd;
public:
ForwardSequenceCursor(I begin, I end)
: myCurrent(current), myEnd(end)
{}
virtual bool has_result () {
return myCurrent != myEnd;
}
virtual value_type get_result () {
return *myCurrent++;
}
};
次に、順方向シーケンスを次のように返すことができます。
class Foo
{
std::vector<int> myValues;
public:
std::unique_ptr< Cursor<int> > values () {
return std::unique_ptr< Cursor<int> >(
new ForwardSequenceCursor<vector<int>::const_iterator>(
myValues.begin(), myValues.end()
)
);
}
};
そして、次のように使用します。
std::unique_ptr< Cursor<int> > cursor = foo.values();
while (cursor->has_result()) {
std::cout << cursor->get_result() << std::endl;
}
他の人が述べたように、クライアントが戻り値を取得する場合、その戻り値が何であるかを知る必要があるため、自分がやろうとしていることを直接行うことはできません。
それを回避する1つの方法は、次のようなことです。
template<typename Collection> class MyClass
{
typedef Collection::iterator ReturnIt;
typedef std::pair<ReturnIt, ReturnIt> IteratorPair;
ReturnIt foo();
IteratorPair bar();
};
さて、これはクライアントがコンテナ型を見ることから私たちを解放するわけではありませんが、インターフェースはコンテナ型にバインドされていません。
あなたが探しているのは、「イテレータの型消去」です。たとえば、次のいずれかを参照してください。
ForwardIterator は概念であり、型ではありません。型を返すには、関数を宣言する必要があります。
タイプ「ForwardIterator」の基本クラスはありません。通常の STL の方法は、クラス内の実際のイテレータ タイプに typedef を設定して、クライアント コードで次のように使用できるようにすることです。
MyClass::iterator it = myclass.begin();
非表示にするほど良くはありませんが、クライアント コードを変更することなく、後で実装を変更できます。