tupleを作ってみた
対数オーダーで作りたくて書き始めたのですが、思ったより難しそうだったのでとりあえず基本の線形実装です。
ムーブコンストラクタ等実装してません…。
実装法は幾つかあると思いますが、これではpairの入れ子による構築、firstをvalue、secondをpairにしてリスト風に実装しています。 継承を用いて実装しているライブラリもあったような気がします。
葉を除いてfirstもsecondもpairにして葉で両方をvalueにする木構造チックな方針で構築すれば対数オーダー化出来る気がします。
今度挑戦してみます。
#include <type_traits> #include "sprout/utility.hpp" #include "toki/traits.hpp" template<class... Types> struct tuple { private: template<class T> struct single_data { constexpr single_data(T arg) : first(arg) {}; const T first; }; template<class T, class... Ts, typename std::enable_if<(sizeof...(Ts) >= 1)>::type*& = toki::enabler> constexpr auto create_tuple(T Arg, Ts... Args) { return sprout::make_pair(Arg, create_tuple(Args...)); } template<class T> constexpr auto create_tuple(T Arg) { return single_data<T>(Arg); } template<class T, class... Ts, typename std::enable_if<(sizeof...(Ts) >= 1)>::type*& = toki::enabler> static auto data_type() { return toki::type_wrapper<sprout::pair<T, typename decltype(data_type<Ts...>())::type>>(); } template<class T> static auto data_type() -> toki::type_wrapper<single_data<T>>; public: constexpr tuple(Types... Args) : data(create_tuple(Args...)) {}; const typename decltype(data_type<Types...>())::type data; }; namespace detail { template<std::size_t N> struct get_impl { template<class T> constexpr auto operator ()(T arg) { return get_impl<N - 1>()(arg.second); } }; template<> struct get_impl<0> { template<class T> constexpr auto operator ()(T arg) { return arg.first; } }; } template<std::size_t N, class T> constexpr auto get(T arg) { return detail::get_impl<N>()(arg.data); } int main() { constexpr tuple<int, double, char> a(1, 2.0, 'a'); static_assert(get<0>(a) == 1, ""); static_assert(get<1>(a) == 2.0, ""); static_assert(get<2>(a) == 'a', ""); }
よくよく考えてみればoperator()()はstaticに出来ますね…。