C++代码片段(五)tuple的实现
元組tuple是多類型的集合,可以當做升級版的pair來用。因為tuple可以保存多個任意類型的值,導致不能夠在一個類里面保存所有的數(shù)據(jù),所以采用每一層保存一個數(shù)據(jù)的方法實現(xiàn)
實現(xiàn)tuple
template <typename... Args> class tuple { };/* 每一層保存一個T類型的數(shù)據(jù) */ template <typename T, typename... Args> class tuple<T, Args...> : public tuple<Args...> {public:tuple() = default;tuple(T&& t, Args&&... args): tuple<Args...>(std::forward<Args>(args)...),value_(std::forward<T>(t)){ }template <std::size_t N>decltype(auto) get() {static_assert(N<=sizeof...(Args));if constexpr (N == 0) {return (value_);}else {return (this->tuple<Args...>::template get<N - 1>());}}template <std::size_t N>decltype(auto) get() const {static_assert(N<=sizeof...(Args));if constexpr (N == 0) {return (value_);}else {return (this->tuple<Args...>::template get<N - 1>());}}protected:T value_; };實現(xiàn)tuple_element
tuple_element<N, Tuple>萃取元組Tuple的第N個類型。依次遍歷每一個模板參數(shù),直到遍歷到第N個后返回,采用繼承的方式保證最外層的tuple_element_helper可以獲取最終的結(jié)果
模板的模板參數(shù)用來偏特化元組類型,目的是萃取出參數(shù)列表
template <std::size_t N, template <typename...> class Tuple, typename... ArgsWrapper> struct tuple_element<N, Tuple<ArgsWrapper...>> {template <std::size_t M, typename T, typename... Args>struct tuple_element_helper : public tuple_element_helper<M-1, Args..., void>{};template <typename T, typename... Args>struct tuple_element_helper<0, T, Args...>{using type = T;};using type = typename tuple_element_helper<N, ArgsWrapper..., void>::type; };template <std::size_t N, typename Tuple> using tuple_element_t = typename tuple_element<N, Tuple>::type;實現(xiàn)tuple_size
tuple_size<Tuple>萃取元組Tuple中包含的數(shù)據(jù)個數(shù)。直接利用模板的模板參數(shù)萃取參數(shù)列表,然后使用sizeof計算參數(shù)列表的個數(shù)即可
template <typename Tuple> struct tuple_size : public std::integral_constant<std::size_t, 0> { };template <template <typename...> class Tuple, typename... Args> struct tuple_size<Tuple<Args...>> : public std::integral_constant<std::size_t, sizeof...(Args)> { };template <typename Tuple> static constexpr inline auto tuple_size_v = tuple_size<Tuple>::value;實現(xiàn)make_tuple
make_tuple根據(jù)參數(shù)創(chuàng)建tuple,引用cppreference上面的標準介紹
創(chuàng)建 tuple 對象,從參數(shù)類型推導目標類型。
對于每個 Types... 中的 Ti , Vtypes... 中的對應類型 Vi 為 std::decay::type ,除非應用 std::decay 對某些類型 X 導致 std::reference_wrapper ,該情況下推導的類型為 X& 。
decay會移除類型的const和volatile限定符以及引用,將左值轉(zhuǎn)換成右值,但是對于reference_wrapper類型需要特殊處理,保證tuple的模板參數(shù)也同樣是引用包裝器
namespace detail {template <typename T>struct unwrap_refwrapper{using type = T;};template <typename T>struct unwrap_refwrapper<std::reference_wrapper<T>>{using type = T&;};template <typename T>using special_decay_t = typename unwrap_refwrapper<std::decay_t<T>>::type; }template <typename... Args> tuple<Args...> make_tuple(Args&&... args) {return tuple<detail::special_decay_t<Args>...>(std::forward<Args>(args)...); }實現(xiàn)tuple_cat
tuple_cat用于將兩個tuple連接起來,依次將每個tuple的數(shù)據(jù)取出放到可變模板參數(shù)列表中,最后重新組裝即可
namespace detail {template <std::size_t N1, std::size_t M1, std::size_t N2, std::size_t M2, typename Tuple1, typename Tuple2, typename... Args>auto tuple_cat_impl(Tuple1&& t1, Tuple2&& t2, Args&&... args) {if constexpr (N1 == M1 && N2 == M2) {return make_tuple(std::forward<Args>(args)...);}else if constexpr (N1 == M1) {return tuple_cat_impl<N1, M1, N2+1, M2>(std::forward<Tuple1>(t1),std::forward<Tuple2>(t2),std::forward<Args>(args)...,t2.template get<N2>());}else {return tuple_cat_impl<N1+1, M1, N2, M2>(std::forward<Tuple1>(t1),std::forward<Tuple2>(t2),std::forward<Args>(args)...,t1.template get<N1>());}} } template <typename... Args1, typename... Args2> auto tuple_cat(const tuple<Args1...>& t1, const tuple<Args2...>& t2) {return detail::tuple_cat_impl<0, sizeof...(Args1), 0, sizeof...(Args2)>(t1, t2); }總結(jié)
以上是生活随笔為你收集整理的C++代码片段(五)tuple的实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库原理学习笔记(二)数据库范式
- 下一篇: 每天一道LeetCode-----找到给