#include <iostream>
#include <algorithm>
#include <type_traits>
#include <vector>
#include <set>
#include <map>
#include <array>
template <class InputContainer, class OutputType>
struct convert_container;
// conversion for the first group of standard containers
template <template <class...> class C, class IT, class OT>
struct convert_container<C<IT>, OT>
{
using type = C<OT>;
};
// conversion for the second group of standard containers
template <template <class...> class C, class IK, class IT, class OK, class OT>
struct convert_container<C<IK, IT>, std::pair<OK, OT>>
{
using type = C<OK, OT>;
};
// conversion for the third group of standard containers
template
<
template <class, std::size_t> class C, std::size_t N, class IT, class OT
>
struct convert_container<C<IT, N>, OT>
{
using type = C<OT, N>;
};
template <typename C, typename T>
using convert_container_t = typename convert_container<C, T>::type;
template
<
class InputContainer,
class Functor,
class InputType = typename InputContainer::value_type,
class OutputType = typename std::result_of<Functor(InputType)>::type,
class OutputContainer = convert_container_t<InputContainer, OutputType>
>
OutputContainer transform_container(const InputContainer& ic, Functor f)
{
OutputContainer oc;
std::transform(std::begin(ic), std::end(ic), std::inserter(oc, oc.end()), f);
return oc;
}
int main()
{
std::cout << std::boolalpha;
std::vector<int> vi{ 1, 2, 3, 4, 5 };
auto vs = transform_container(vi, [] (int i) { return std::to_string(i); });
std::cout << "std::vector<int> -> std::vector<std::string>: "
<< (vs == std::vector<std::string>{"1", "2", "3", "4", "5"}) << std::endl;
std::set<int> si{ 5, 10, 15 };
auto sd = transform_container(si, [] (int i) { return i / 2.; });
std::cout << "std::set<int> -> std::set<double>: "
<< (sd == std::set<double>{5/2., 10/2., 15/2.}) << std::endl;
std::map<int, char> mic{ {1, 'a'}, {2, 'b'}, {3, 'c'} };
auto mci = transform_container
(
mic,
[] (const std::pair<const int, char>& p)
{ return std::pair<char, int>(p.second, p.first); }
);
std::cout << "std::map<int, char> -> std::map<char, int>: "
<< (mci == std::map<char, int>{{'a', 1}, {'b', 2}, {'c', 3}}) << std::endl;
// doesn't compile because std::array haven't insert method
// which is needed due to std::inserter
/*std::array<int, 3> ai{ 5, 10, 15 };
auto ad = transform_container(ai, [] (int i) { return i / 2.; });
std::cout << "std::array<int, 3> -> std::array<double, 3>: "
<< (ad == std::array<double, 3>{5/2., 10/2., 15/2.}) << std::endl;*/
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDxzZXQ+CiNpbmNsdWRlIDxtYXA+CiNpbmNsdWRlIDxhcnJheT4KCgp0ZW1wbGF0ZSA8Y2xhc3MgSW5wdXRDb250YWluZXIsIGNsYXNzIE91dHB1dFR5cGU+CnN0cnVjdCBjb252ZXJ0X2NvbnRhaW5lcjsKCi8vIGNvbnZlcnNpb24gZm9yIHRoZSBmaXJzdCBncm91cCBvZiBzdGFuZGFyZCBjb250YWluZXJzCnRlbXBsYXRlIDx0ZW1wbGF0ZSA8Y2xhc3MuLi4+IGNsYXNzIEMsIGNsYXNzIElULCBjbGFzcyBPVD4Kc3RydWN0IGNvbnZlcnRfY29udGFpbmVyPEM8SVQ+LCBPVD4KewogICAgdXNpbmcgdHlwZSA9IEM8T1Q+Owp9OwoKLy8gY29udmVyc2lvbiBmb3IgdGhlIHNlY29uZCBncm91cCBvZiBzdGFuZGFyZCBjb250YWluZXJzCnRlbXBsYXRlIDx0ZW1wbGF0ZSA8Y2xhc3MuLi4+IGNsYXNzIEMsIGNsYXNzIElLLCBjbGFzcyBJVCwgY2xhc3MgT0ssIGNsYXNzIE9UPgpzdHJ1Y3QgY29udmVydF9jb250YWluZXI8QzxJSywgSVQ+LCBzdGQ6OnBhaXI8T0ssIE9UPj4KewogICAgdXNpbmcgdHlwZSA9IEM8T0ssIE9UPjsKfTsKCi8vIGNvbnZlcnNpb24gZm9yIHRoZSB0aGlyZCBncm91cCBvZiBzdGFuZGFyZCBjb250YWluZXJzCnRlbXBsYXRlCiAgICA8CiAgICAgICAgdGVtcGxhdGUgPGNsYXNzLCBzdGQ6OnNpemVfdD4gY2xhc3MgQywgc3RkOjpzaXplX3QgTiwgY2xhc3MgSVQsIGNsYXNzIE9UCiAgICA+CnN0cnVjdCBjb252ZXJ0X2NvbnRhaW5lcjxDPElULCBOPiwgT1Q+CnsKICAgIHVzaW5nIHR5cGUgPSBDPE9ULCBOPjsKfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBDLCB0eXBlbmFtZSBUPgp1c2luZyBjb252ZXJ0X2NvbnRhaW5lcl90ID0gdHlwZW5hbWUgY29udmVydF9jb250YWluZXI8QywgVD46OnR5cGU7Cgp0ZW1wbGF0ZQogICAgPAogICAgICAgIGNsYXNzIElucHV0Q29udGFpbmVyLAogICAgICAgIGNsYXNzIEZ1bmN0b3IsCiAgICAgICAgY2xhc3MgSW5wdXRUeXBlID0gdHlwZW5hbWUgSW5wdXRDb250YWluZXI6OnZhbHVlX3R5cGUsCiAgICAgICAgY2xhc3MgT3V0cHV0VHlwZSA9IHR5cGVuYW1lIHN0ZDo6cmVzdWx0X29mPEZ1bmN0b3IoSW5wdXRUeXBlKT46OnR5cGUsCiAgICAgICAgY2xhc3MgT3V0cHV0Q29udGFpbmVyID0gY29udmVydF9jb250YWluZXJfdDxJbnB1dENvbnRhaW5lciwgT3V0cHV0VHlwZT4KICAgID4KT3V0cHV0Q29udGFpbmVyIHRyYW5zZm9ybV9jb250YWluZXIoY29uc3QgSW5wdXRDb250YWluZXImIGljLCBGdW5jdG9yIGYpCnsKICAgIE91dHB1dENvbnRhaW5lciBvYzsKCiAgICBzdGQ6OnRyYW5zZm9ybShzdGQ6OmJlZ2luKGljKSwgc3RkOjplbmQoaWMpLCBzdGQ6Omluc2VydGVyKG9jLCBvYy5lbmQoKSksIGYpOwoKICAgIHJldHVybiBvYzsKfQoKaW50IG1haW4oKQp7CiAgICBzdGQ6OmNvdXQgPDwgc3RkOjpib29sYWxwaGE7CiAgICAKICAgIHN0ZDo6dmVjdG9yPGludD4gdml7IDEsIDIsIDMsIDQsIDUgfTsKICAgIGF1dG8gdnMgPSB0cmFuc2Zvcm1fY29udGFpbmVyKHZpLCBbXSAoaW50IGkpIHsgcmV0dXJuIHN0ZDo6dG9fc3RyaW5nKGkpOyB9KTsgCiAgICBzdGQ6OmNvdXQgPDwgInN0ZDo6dmVjdG9yPGludD4gLT4gc3RkOjp2ZWN0b3I8c3RkOjpzdHJpbmc+OiAiCiAgICAgICAgPDwgKHZzID09IHN0ZDo6dmVjdG9yPHN0ZDo6c3RyaW5nPnsiMSIsICIyIiwgIjMiLCAiNCIsICI1In0pIDw8IHN0ZDo6ZW5kbDsKICAgICAgICAKICAgIHN0ZDo6c2V0PGludD4gc2l7IDUsIDEwLCAxNSB9OwogICAgYXV0byBzZCA9IHRyYW5zZm9ybV9jb250YWluZXIoc2ksIFtdIChpbnQgaSkgeyByZXR1cm4gaSAvIDIuOyB9KTsgCiAgICBzdGQ6OmNvdXQgPDwgInN0ZDo6c2V0PGludD4gLT4gc3RkOjpzZXQ8ZG91YmxlPjogIgogICAgICAgIDw8IChzZCA9PSBzdGQ6OnNldDxkb3VibGU+ezUvMi4sIDEwLzIuLCAxNS8yLn0pIDw8IHN0ZDo6ZW5kbDsKICAgIAogICAgc3RkOjptYXA8aW50LCBjaGFyPiBtaWN7IHsxLCAnYSd9LCB7MiwgJ2InfSwgezMsICdjJ30gfTsKICAgIGF1dG8gbWNpID0gdHJhbnNmb3JtX2NvbnRhaW5lcgogICAgICAgICgKICAgICAgICAgICAgbWljLAogICAgICAgICAgICBbXSAoY29uc3Qgc3RkOjpwYWlyPGNvbnN0IGludCwgY2hhcj4mIHApCiAgICAgICAgICAgIHsgcmV0dXJuIHN0ZDo6cGFpcjxjaGFyLCBpbnQ+KHAuc2Vjb25kLCBwLmZpcnN0KTsgfQogICAgICAgICk7IAogICAgc3RkOjpjb3V0IDw8ICJzdGQ6Om1hcDxpbnQsIGNoYXI+IC0+IHN0ZDo6bWFwPGNoYXIsIGludD46ICIKICAgICAgICA8PCAobWNpID09IHN0ZDo6bWFwPGNoYXIsIGludD57eydhJywgMX0sIHsnYicsIDJ9LCB7J2MnLCAzfX0pIDw8IHN0ZDo6ZW5kbDsKICAgIAogICAgLy8gZG9lc24ndCBjb21waWxlIGJlY2F1c2Ugc3RkOjphcnJheSBoYXZlbid0IGluc2VydCBtZXRob2QKICAgIC8vIHdoaWNoIGlzIG5lZWRlZCBkdWUgdG8gc3RkOjppbnNlcnRlcgogICAgLypzdGQ6OmFycmF5PGludCwgMz4gYWl7IDUsIDEwLCAxNSB9OwogICAgYXV0byBhZCA9IHRyYW5zZm9ybV9jb250YWluZXIoYWksIFtdIChpbnQgaSkgeyByZXR1cm4gaSAvIDIuOyB9KTsgCiAgICBzdGQ6OmNvdXQgPDwgInN0ZDo6YXJyYXk8aW50LCAzPiAtPiBzdGQ6OmFycmF5PGRvdWJsZSwgMz46ICIKICAgICAgICA8PCAoYWQgPT0gc3RkOjphcnJheTxkb3VibGUsIDM+ezUvMi4sIDEwLzIuLCAxNS8yLn0pIDw8IHN0ZDo6ZW5kbDsqLwp9