少し前に、可変個引数テンプレートのおかげで、Python の chain 関数に相当する C++ を実装しました。この関数は、多くのコンテナーを連続して反復処理するために使用されます。ChainedObject
これは、名前が何であれ、という名前のジェネレーターを使用した関数の古い作業バージョンです。
template<typename... Iterables>
auto chain(Iterables&&... iters)
-> ChainObject<Iterables...>
{
return /* ... */;
}
そして対応するメイン:
int main()
{
std::vector<int> vec = { 1, 2, 3, 4, 5 };
std::list<int> li = { 6, 7, 8, 9, 10, 11, 12, 13 };
for (auto& i: chain(vec, li))
{
// You can edit a range of iterables
// as if there was only one of them.
i *= 5;
std::cout << i << std::endl;
}
return 0;
}
そのメインはうまくいきました。問題の ChainObject に何があるかは気にしないので、見てみましょう。テンプレート テンプレートを使用して、使用されるさまざまなコレクションが同じであることを確認しvalue_type
、関数chain
を次のように変更しようとしました。
template<typename T, template<typename...> class... Iterables>
auto chain(Iterables<T>&&... iters)
-> ChainObject<T, Iterables...>
{
return /* ... */;
}
list
これにより、以前のメイン共有のandが同じ型を共有するようにするためのトリックが行われると考えましたvector
が、代わりに、GCC 4.7.1 から次のエラーが発生します。
関数 'int main()' 内:
エラー: 'chain(std::vector&, std::list&)' の呼び出しに一致する関数がありません
注: 候補は次のとおりです。
注:
ChainObject<T, Iterables ...> chain(Iterables<T>&& ...) [with T = int; Iterables = {std::vector, std::list}
]注: ' ' から ' ' への引数 2 の既知の変換はありませ
std::list<int>
んstd::list<int>&&
ノート:
ChainObject<T, Iterables ...> chain(Iterables<T>&& ...) [with T = int; Iterables = {std::vector, std::list}]
注: ' ' から ' ' への引数 2 の既知の変換はありませ
std::list<int>
んstd::list<int>&&
エラー: '' から 'auto&' を推測できません
問題は、右辺値参照を取る関数への引数の受け渡しにあるようです。しかし、最初のバージョンがうまく機能した理由がよくわかりません。テンプレート テンプレートを使用していることに注意してください。