c++ - Swapping two elements in a template type list. Seeking most efficient algorithm -
swap<t, position1, position2, pack>::type
, pack
consists of elements of type t, return pack elements in position1 , position2 swapped. solution below not efficient. there should way accomplish cleanly, without visiting element twice. can think of it?
// replaceelement replaces element of pack specified position (0 being first position) specified value. template <typename t, std::size_t, std::size_t, t, typename, typename> struct replaceelementhelper; template <typename t, std::size_t position, std::size_t currentposition, t newvalue, template <t...> class z, t first, t... rest, t... accumulated> struct replaceelementhelper<t, position, currentposition, newvalue, z<first, rest...>, z<accumulated...>> : replaceelementhelper<t, position, currentposition + 1, newvalue, z<rest...>, z<accumulated..., first>> {}; template <typename t, std::size_t position, t newvalue, template <t...> class z, t first, t... rest, t... accumulated> struct replaceelementhelper<t, position, position, newvalue, z<first, rest...>, z<accumulated...>> { using type = z<accumulated..., newvalue, rest...>; }; template <typename t, std::size_t, t, typename> struct replaceelement; template <typename t, std::size_t position, t newvalue, template <t...> class z, t... ts> struct replaceelement<t, position, newvalue, z<ts...>> : replaceelementhelper<t, position, 0, newvalue, z<ts...>, z<>> { static_assert (position < sizeof...(ts), "error! invalid position replaceelement."); }; // swapping 2 elements of specified positions in pack. template <typename, std::size_t, std::size_t, typename> struct swap; template <typename t, std::size_t position1, std::size_t position2, template <t...> class z, t... ts> struct swap<t, position1, position2, z<ts...>> { static constexpr t a[sizeof...(ts)] = {ts...}; using type = typename replaceelement<t, position2, a[position1], typename replaceelement<t, position1, a[position2], z<ts...>>::type>::type; };
you can tell solution visits all
elements before position1 (or position2) twice. there should no need that. know there must solution avoids this, can't think of it.
provided value_pack
defined like
template <typename t, t... v> struct value_pack { static constexpr t array[] {v...}; static constexpr std::size_t len = sizeof...(v); using type = value_pack; }; template <typename t, t... v> constexpr t value_pack<t, v...>::array[];
then solution in c++14 looks this:
template <typename t, std::size_t p1, std::size_t p2, typename pack, typename=std::make_index_sequence<pack::len>> struct swap; template <typename t, std::size_t p1, std::size_t p2, typename pack, std::size_t...indices> struct swap<t, p1, p2, pack, std::index_sequence<indices...>> : value_pack<t, pack::array[indices==p1? p2 : indices==p2? p1 : indices]...> {};
demo. if c++14 standard library not available, can implement make_index_sequence
- numerous examples scattered across so.
Comments
Post a Comment