Type List(C++ 模板元编程)

这篇具有很好参考价值的文章主要介绍了Type List(C++ 模板元编程)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

定义

类型列表,字面意思就是一个存储类型的列表,例如std::tuple<int, float, double, std::string>就是一个类型列表。

template<typename ...Ts> struct type_list {};

基础操作

操作约束:对于所有操作,均要求参数合法,即要求type_list中至少有一个类型,或者提供的下标不越界。

  • is_empty

  • front

  • pop_front

  • push_front

  • push_back

  • back

  • pop_back

  • reverse

  • largest(支持自定义compare)

  • merge

  • insert

is_empty

template<typename Ts>
struct is_empty_impl : std::integral_constant<bool, false> {};

template<>
struct is_empty_impl<type_list<>> : std::integral_constant<bool, true> {};

template<typename Ts>
constexpr static bool is_empty = is_empty_impl<Ts>::value;

Front

template<typename T> struct front_impl {};

template<typename T, typename ...Ts>
struct front_impl<type_list<T, Ts...>> {
  using type = T;
};

template<typename T> using front = front_impl<T>::type;

Pop front

template<typename T> struct pop_front_impl {};

template<typename T, typename ...Ts>
struct pop_front_impl<type_list<T, Ts...>> {
  using type = type_list<Ts...>;
};

template<typename T> using pop_front = pop_front_impl<T>::type;

Push front

template<typename Tl, typename T> struct push_front_impl {};

template<typename ...Ts, typename T>
struct push_front_impl<type_list<Ts...>, T> {
  using type = type_list<T, Ts...>;
};

template<typename Tl, typename T>
using push_front = push_front_impl<Tl, T>::type;

Push back

template<typename Tl, typename T> struct push_back_impl {};

template<typename ...Ts, typename T>
struct push_back_impl<type_list<Ts...>, T> {
  using type = type_list<Ts..., T>;
};

template<typename Tl, typename T>
using push_back = push_back_impl<Tl, T>::type;

Back

template<typename Tl> struct back_impl {};

template<typename T, typename ...Ts>
struct back_impl<type_list<T, Ts...>> : back_impl<type_list<Ts...>> {};

template<typename T>
struct back_impl<type_list<T>> { using type = T; };

template<typename Tl> using back = back_impl<Tl>::type;

Pop back

template<typename Tl> struct pop_back_impl {};

template<typename T, typename ...Ts>
struct pop_back_impl<type_list<T, Ts...>>
    : push_front_impl<typename pop_back_impl<type_list<Ts...>>::type, T> {};

template<typename T>
struct pop_back_impl<type_list<T>> { using type = type_list<>; };

template<typename Tl> using pop_back = pop_back_impl<Tl>::type;

Reverse

template<typename Tl, bool empty = is_empty<Tl>> struct reverse_impl {};

template<typename Tl>
struct reverse_impl<Tl, false>
    : push_back_impl<typename reverse_impl<pop_front<Tl>>::type, front<Tl>> {};

template<typename Tl>
struct reverse_impl<Tl, true> { using type = type_list<>; };

template<typename Tl>
using reverse = reverse_impl<Tl>::type;

Largest (可接收自定义类型比较函数:参考compare实现)

template<bool judge, typename T1, typename T2>
struct type_choose {
  using type = T2;
};

template<typename T1, typename T2>
struct type_choose<true, T1, T2> {
  using type = T1;
};

template<typename T1, typename T2>
struct compare : std::integral_constant<bool, false> {};

template<typename T1, typename T2>
requires (sizeof(T1) > sizeof(T2))
struct compare<T1, T2> : std::integral_constant<bool, true> {};

template<typename Tl, template<typename ...> typename C> struct largest_impl {};

template<typename T, template<typename ...> typename C>
struct largest_impl<type_list<T>, C> {
  using type = T;
};

template<typename T, typename ...Ts, template<typename ...> typename C>
struct largest_impl<type_list<T, Ts...>, C>
    : type_choose<C<T, typename largest_impl<type_list<Ts...>, C>::type>::value,
                  T, typename largest_impl<type_list<Ts...>, C>::type> {};

template<typename Tl, template<typename ...> typename C>
using largest = largest_impl<Tl, C>::type;

merge

template<typename Tl1, typename Tl2> struct merge_impl {};

template<typename ...Ts1, typename ...Ts2>
struct merge_impl<type_list<Ts1...>, type_list<Ts2...>> {
  using type = type_list<Ts1..., Ts2...>;
};

template<typename Tl1, typename Tl2>
using merge = merge_impl<Tl1, Tl2>::type;

insert

两个子模板会在insert_impl<type_list<Ts...>, 0, T> sizeof...(Ts) > 0的时候冲突,所以加上一个requires约束一下。

template<typename Tl, int index, typename T> struct insert_impl {};

template<typename Tf, typename ...Ts, int index, typename T>
requires (index > 0)
struct insert_impl<type_list<Tf, Ts...>, index, T>
    : push_front_impl<typename insert_impl<type_list<Ts...>, index - 1, T>::type, Tf> {};

template<typename ...Ts, typename T>
struct insert_impl<type_list<Ts...>, 0, T>
    : push_front_impl<type_list<Ts...>, T> {};

template<typename Tl, int index, typename T>
using insert = insert_impl<Tl, index, T>::type;

TEST

符合TDD,简单测试一下:

int main() {
   // is empty: 1 0 0
  std::cout << "is empty: ";
  std::cout << is_empty<type_list<>> << " "
            << is_empty<type_list<int>> << " "
            << is_empty<type_list<int, float, double>> << "\n\n";

  // front: 1 0
  std::cout << "front: ";
  std::cout << std::is_same_v<int, front<type_list<int, float>>> << " "
            << std::is_same_v<float, front<type_list<int, float>>> << "\n\n";

  // pop front: 1 0 1
  std::cout << "pop front: ";
  std::cout << std::is_same_v<type_list<>, pop_front<type_list<int>>> << " "
            << std::is_same_v<type_list<int>, pop_front<type_list<int>>> << " "
            << std::is_same_v<type_list<int>, pop_front<type_list<float, int>>> << "\n\n";

  // push front: 1 0 1
  std::cout << "push front: ";
  std::cout << std::is_same_v<type_list<int>, push_front<type_list<>, int>> << " "
            << std::is_same_v<type_list<int, float>, push_front<type_list<int>, float>> << " "
            << std::is_same_v<type_list<float, int>, push_front<type_list<int>, float>> << "\n\n";

  // push back: 1 1 0
  std::cout << "push back: ";
  std::cout << std::is_same_v<type_list<int>, push_back<type_list<>, int>> << " "
            << std::is_same_v<type_list<int, float>, push_back<type_list<int>, float>> << " "
            << std::is_same_v<type_list<float, int>, push_back<type_list<int>, float>> << "\n\n";

  // back: 1 0 1
  std::cout << "back: ";
  std::cout << std::is_same_v<int, back<type_list<int>>> << " "
            << std::is_same_v<int, back<type_list<int, float>>> << " "
            << std::is_same_v<float, back<type_list<int, float>>> << "\n\n";

  // pop back: 1 1 0
  std::cout << "pop back: ";
  std::cout << std::is_same_v<type_list<>, pop_back<type_list<int>>> << " "
            << std::is_same_v<type_list<float>, pop_back<type_list<float, int>>> << " "
            << std::is_same_v<type_list<int>, pop_back<type_list<float, int>>> << "\n\n";

  // reverse: 1 0 1 1
  std::cout << "reverse: ";
  std::cout << std::is_same_v<type_list<>, reverse<type_list<>>> << " "
            << std::is_same_v<type_list<int, float>, reverse<type_list<int, float>>> << " "
            << std::is_same_v<type_list<float, int>, reverse<type_list<int, float>>> << " "
            << std::is_same_v<type_list<int, float, double>, reverse<type_list<double, float, int>>> << "\n\n";

  // largest: 1, 0, 1
  // char, short, int32_t, int64_t, double
  std::cout << sizeof(char) << " " << sizeof(short) << " " << sizeof(int32_t)
            << " " << sizeof(int64_t) << " " << sizeof(double) << "\n";
  using type1 = type_list<char, short, int32_t, int64_t, double>;
  using type2 = type_list<char, short, int32_t, double, int64_t>;
  std::cout << "largest: ";
  std::cout << std::is_same_v<double, largest<type1, compare>> << " "
            << std::is_same_v<double, largest<type2, compare>> << " "
            << std::is_same_v<int64_t, largest<type2, compare>> << "\n\n";

  // merge: 1 1 1 0
  std::cout << "merge: ";
  std::cout << std::is_same_v<type_list<int>, merge<type_list<>, type_list<int>>> << " "
            << std::is_same_v<type_list<int>, merge<type_list<int>, type_list<>>> << " "
            << std::is_same_v<type_list<int, float>, merge<type_list<int>, type_list<float>>> << " "
            << std::is_same_v<type_list<int, float>, merge<type_list<float>, type_list<int>>> << "\n\n";

  // insert: 1 1 1
  std::cout << "insert: ";
  std::cout << std::is_same_v<type_list<int>, insert<type_list<>, 0, int>> << " "
            << std::is_same_v<type_list<int, float, double>, insert<type_list<int, double>, 1, float>> << " "
            << std::is_same_v<type_list<int, float, double>, insert<type_list<int, float>, 2, double>> << "\n";
  return 0;
}

Algorithm

Insert sort

维护尾部的有序性,每次加入一个新值,同时保证尾部的有效性,那么先实现一个insert_in_sorted<type_list<Ts...>, T>文章来源地址https://www.toymoban.com/news/detail-743251.html

  • 找到第一个满足C的位置,并且在这个值前面插入
template<typename Tl, typename T, template<typename ...> typename C,
          bool empty = is_empty<Tl>>
struct insert_in_sorted_impl {};

template<typename ...Ts, typename T, template<typename ...> typename C>
struct insert_in_sorted_impl<type_list<Ts...>, T, C, false>
    : type_choose<(C<front<type_list<Ts...>>, T>::value),
                  push_front<type_list<Ts...>, T>,
                  push_front<
                      typename insert_in_sorted_impl<pop_front<type_list<Ts...>>, T, C>::type,
                      front<type_list<Ts...>>>
                  > {};

template<typename ...Ts, typename T, template<typename ...> typename C>
struct insert_in_sorted_impl<type_list<Ts...>, T, C, true> {
  using type = type_list<T>;
};

template<typename Tl, typename T, template<typename ...> typename C>
using insert_in_sorted = insert_in_sorted_impl<Tl, T, C>::type;
  • 排序实现
template<typename Tl, template<typename ...> typename C,
          bool empty = is_empty<Tl>> struct insert_sort_impl {};

template<typename ...Ts, template<typename ...> typename C>
struct insert_sort_impl<type_list<Ts...>, C, true> {
  using type = type_list<>;
};

template<typename ...Ts, template<typename ...> typename C>
struct insert_sort_impl<type_list<Ts...>, C, false>
    : insert_in_sorted_impl<
          typename insert_sort_impl<pop_front<type_list<Ts...>>, C>::type,
          front<type_list<Ts...>>, C> {};

template<typename Tl, template<typename ...> typename C>
using insert_sort = insert_sort_impl<Tl, C>::type;
  • 测试一下结果对不对
int main() {
   // insert in sorted: 1 1 1 1 1
  std::cout << "insert in sorted: ";
  std::cout << std::is_same_v<type_list<int32_t>, insert_in_sorted<type_list<>, int32_t , compare>> << " "
            << std::is_same_v<type_list<char, short, int32_t, int64_t>, insert_in_sorted<type_list<char, short, int32_t>, int64_t, compare>> << " "
            << std::is_same_v<type_list<char, short, int32_t, int64_t>, insert_in_sorted<type_list<char, short, int64_t>, int32_t, compare>> << " "
            << std::is_same_v<type_list<char, short, int32_t, float, int64_t>, insert_in_sorted<type_list<char, short, int32_t, int64_t>, float, compare>> << " "
            << std::is_same_v<type_list<char, int32_t, long long, float, int64_t>, insert_in_sorted<type_list<char, long long, float, int64_t>, int32_t, compare>> << "\n";

  // insert sort: 1 1 1 1
  std::cout << "insert sort: ";
  std::cout << std::is_same_v<type_list<>, insert_sort<type_list<>, compare>> << " "
            << std::is_same_v<type_list<char>, insert_sort<type_list<char>, compare>> << " "
            << std::is_same_v<type_list<float, int>, insert_sort<type_list<int, float>, compare>> << " ";

  // 非稳定排序,相同大小的类型,初始在前面的会跑到后面去
  using type_list_sort = type_list<short int, char, short, int, long long, unsigned int, unsigned, unsigned long long, unsigned char>;
  using type_list_sort_ans = type_list<unsigned char, char, short, short int, unsigned, unsigned int, int, unsigned long long, long long>;
  std::cout << std::is_same_v<type_list_sort_ans, insert_sort<type_list_sort, compare>> << "\n";
  return 0;
}

到了这里,关于Type List(C++ 模板元编程)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【C++】——模板(泛型编程+函数模板+类模板)

    【C++】——模板(泛型编程+函数模板+类模板)

    之前我们学习了函数重载,让我们在写相似函数的时候非常方便,但函数重载还有很多不足的地方,比如,每次写相似函数的时候,都要我们重新重载一个逻辑、代码几乎一样的函数,这就导致了我们的效率变低,所以我们今天来学习C++模板的相关知识点,学习完模板之后,

    2024年02月05日
    浏览(10)
  • 【C++初阶】八、初识模板(泛型编程、函数模板、类模板)

    【C++初阶】八、初识模板(泛型编程、函数模板、类模板)

    ========================================================================= 相关代码gitee自取 : C语言学习日记: 加油努力 (gitee.com)  ========================================================================= 接上期 : 【C++初阶】七、内存管理 (C/C++内存分布、C++内存管理方式、operator new / delete 函数、定位new表

    2024年02月04日
    浏览(9)
  • c++模板编程2-函数模板的定义和使用

    两阶段编译检查 在实例化模板的时候,如果模板的参数类型不支持模板中用到的操作符,将会遇到编译期错误,例: 以上例子 add(a, b) 会在编译器报错,但在模板定义的地方并没有出现错误提示,这是因为模板是分两步编译的: 在模板定义阶段,模板的检查并不包含类型参

    2024年02月06日
    浏览(5)
  • C++之模板编程

    模板及泛型编程与面向对象有根本的区别:显式接口和运行期多态仍存在,但重要性降低,隐式接口和编译期多态移到前头了;C++中的元编程指针对类型以及常数进行推导,演算和构造等操作,这些操作的共同特点是都是面向编译期逻辑,大多通过模板技巧实现 经验总结 只

    2024年02月03日
    浏览(9)
  • C++提高编程——模板

    C++提高编程——模板

    本阶段主要针对C++ 泛型编程 和 STT 技术 做详细讲解,探讨C++更深层的使用 模板就是建立通用的模具,大大提高复用性 例如生活中的模板 寸照片模板: C++另一种编程思想称为 泛型编程 ,主要利用的技术就是模板 C++提供两种模板机制:函数模板和类模板 1.2.1函数模板语法 函

    2024年02月12日
    浏览(10)
  • 【C++】C++泛型编程 | 模板初阶

    【C++】C++泛型编程 | 模板初阶

      🧑‍🎓 个人主页:简 料   🏆 所属专栏:C++   🏆 个人社区:越努力越幸运社区   🏆 简       介: 简料简料,简单有料~在校大学生一枚,专注C/C++/GO的干货分享,立志成为您的好帮手 ~ C/C++学习路线 (点击解锁) ❤️ C语言 ❤️ 初阶数据结构与算法 ❤️ C++ ❤️

    2024年02月08日
    浏览(9)
  • C++核心编程——详解函数模板

    C++核心编程——详解函数模板

    纵有疾风起,人生不言弃。本文篇幅较长,如有错误请不吝赐教,感谢支持。 ①为什么有模板? 在C++程序中,声明变量、函数、对象等实体时,程序设计者需要指定数据类型,让编译器在程序运行之前进行类型检查并分配内存,以提高程序运行的安全性和效率。 但是这种强

    2024年02月09日
    浏览(10)
  • C++泛型编程之模板

    C++泛型编程之模板

    目录 一、什么是泛型编程  二、函数模板 2.1函数模板的概念 2.2函数模板格式 2.3函数模板的原理  2.5函数模板的实例化 2.6模板参数的匹配原则 三、类模板 3.1类模板的定义格式 3.2 类模板的实例化 四、非类型模板参数 五、模板的特化 5.1模板特化的概念: 5.2函数模板特化 5

    2024年02月07日
    浏览(10)
  • 【C++】泛型编程——模板进阶

    【C++】泛型编程——模板进阶

    在之前的文章里,我们进行了模板初阶的学习( 【C++】泛型编程——模板初阶),了解了什么是泛型编程,学习了函数模板和类模板。 那这篇文章,我们继续学习模板进阶的内容的学习。 首先我们来回顾一下: 我们在模板初阶的学习中,定义模板参数是怎么定义的? 是不

    2024年02月16日
    浏览(10)
  • C++ 泛型编程:函数模板

    C++ 泛型编程:函数模板

    当需要编写通用的代码以处理不同类型的数据时,C++ 中的函数模板是一个很有用的工具。函数模板允许我们编写一个通用的函数定义,可以用于多种不同的数据类型,从而提高代码的重用性和灵活性。 泛型编程 是一种编程范式,旨在实现可重用、通用性高的代码。它允许我

    2024年02月12日
    浏览(9)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包