さて、これから始めることができます:
template<typename Output, typename Input, typename Transformation>
auto transform( Input const& input, Transformation t )->Output {
Output retval;
retval.reserve(input.size());
using std::cbegin; using std::cend;
std::transform(cbegin(input), cend(input), std::back_inserter(retval));
return retval;
}
次に、次のような作業を行います。
namespace aux{
using std::cbegin;
template<typename T>
auto adl_cbegin( T&& t )->decltype(cbegin(std::forward(t)));
}
template<typename Input, typename Transformation>
auto transform_vec( Input const& input, Transformation t )->
std::vector<typename std::remove_ref<decltype(t(*adl_cbegin(input)))>::type>
{
typedef std::vector<typename std::remove_ref<decltype(t(*adl_cbegin(input)))>::type> Output;
Output retval;
// retval.reserve(input.size()); -- need a way to do this if Input has an easy way to get size. Too lazy to bother right now.
using std::cbegin; using std::cend;
std::transform(cbegin(input), cend(input), std::back_inserter(retval));
return retval;
}
注:これは反復可能なもの(ベクトル、配列、イテレーターのペア)を取り、そこから入力範囲でstd::pair
のを生成するようにアップグレードするboost::transform_iterator
ため、結果の変換を任意のコンテナーに挿入できます。実際にイテレータを逆参照すると、変換が機能します。
または、ご存知のとおり、std::back_inserter(input)
直接使用してください。:)そのアプローチの欠点は、リザーブを実行しないため、パフォーマンスに影響が出るということです。