调用带有类型名称组合的模板函数

huangapple go评论98阅读模式
英文:

Call template function with typename combinations

问题

我想循环遍历一个"类型名称列表",并查看它们的所有组合。我考虑使用元组来实现这一点,比较:

  1. template<typename T, typename R>
  2. void foo() {
  3. std::cout << std::numeric_limits<T>::max() << ", " << std::numeric_limits<R>::max();
  4. }
  5. void call() {
  6. using int_types = std::tuple<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t>;
  7. // 只是为了可视化我的想法,这段代码不起作用!(请参见注释)
  8. constexpr auto indices = std::make_integer_sequence<size_t, 8>();
  9. for (auto i: indices) {
  10. using T = std::tuple_element_t<i, int_types>;
  11. for (auto j: indices) {
  12. using R = std::tuple_element_t<j, int_types>;
  13. foo<T, R>();
  14. }
  15. }
  16. }

当然,for循环不是consteval,因此这种方法不起作用。我认为可以使用STL的递归或一些consteval功能来解决,但我还没有完全弄清楚。

英文:

I want to loop over a "list of typenames" and look at all combinations of them. I was thinking of using a tuple for this, compare:

  1. template&lt;typename T, typename R&gt;
  2. void foo() {
  3. std::cout &lt;&lt; std::numeric_limits&lt;T&gt;::max() &lt;&lt; &quot;, &quot; &lt;&lt; std::numeric_limits&lt;R&gt;::max();
  4. }
  5. void call() {
  6. using int_types = std::tuple&lt;int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t&gt;;
  7. //Just to visualize my idea, this code does not work! (see comments)
  8. constexpr auto indices = std::make_integer_sequence&lt;size_t, 8&gt;();
  9. for (auto i: indices) {
  10. using T = std::tuple_element_t&lt;i, int_types&gt;;
  11. for (auto j: indices) {
  12. using R = std::tuple_element_t&lt;j, int_types&gt;;
  13. foo&lt;T, R&gt;();
  14. }
  15. }
  16. }

Of course for loops are not consteval, thus this approach does not work. I think it might work using recursion or some consteval stuff from the STL but I can't quite figure it out.

答案1

得分: 2

  1. 您可以以这种方式扩展包

使用 int_types = std::tuple<int8_t, uint8_t, int16_t, uint16_t,
int32_t, uint32_t, int64_t, uint64_t>;

[]<typename... Ts>(std::tuple<Ts...>){
[]<typename T, typename... Us>(std::type_identity, std::tuple<Us...>){
(foo<T, Us>(), ...);
}(std::type_identity{}, int_types{}), ...);
}(int_types{});

  1. [演示](https://godbolt.org/z/K7K9q3hPG)
英文:

You can expand pack that way

  1. using int_types = std::tuple&lt;int8_t, uint8_t, int16_t, uint16_t,
  2. int32_t, uint32_t, int64_t, uint64_t&gt;;
  3. []&lt;typename... Ts&gt;(std::tuple&lt;Ts...&gt;){
  4. ([]&lt;typename T, typename... Us&gt;(std::type_identity&lt;T&gt;, std::tuple&lt;Us...&gt;){
  5. (foo&lt;T, Us&gt;(), ...);
  6. }(std::type_identity&lt;Ts&gt;{}, int_types{}), ...);
  7. }(int_types{});

Demo

答案2

得分: 2

这是一个基于索引的版本,其中内部 lambda 函数可以访问具体的索引,比如 LK。在这个版本中,如果需要的话,你可以进行验证,例如,如果索引相等,你可以选择排除对 foo 的调用:

  1. void call() {
  2. using int_types = std::tuple<int8_t, uint8_t, int16_t, uint16_t, int32_t,
  3. uint32_t, int64_t, uint64_t>;
  4. constexpr auto tsize = std::tuple_size_v<int_types>;
  5. []<std::size_t... Is>(std::index_sequence<Is...>) {
  6. ( // 折叠 1
  7. []<size_t I, std::size_t... Js>(std::integral_constant<std::size_t, I>,
  8. std::index_sequence<Js...>)
  9. {
  10. ( // 折叠 2:
  11. []<std::size_t K, std::size_t L>(
  12. std::integral_constant<std::size_t, K>,
  13. std::integral_constant<std::size_t, L>)
  14. {
  15. if constexpr(K != L) foo<std::tuple_element_t<K, int_types>,
  16. std::tuple_element_t<L, int_types>>();
  17. }(std::integral_constant<std::size_t, I>(),
  18. std::integral_constant<std::size_t, Js>()),
  19. ...);
  20. }(std::integral_constant<std::size_t, Is>(),
  21. std::make_index_sequence<tsize>()),
  22. ...);
  23. }(std::make_index_sequence<tsize>());
  24. }

演示

英文:

Here's an index based version where the inner lambda has access to the concrete indices, here L and K. In that you can do validation if you want to exclude calls to foo if the indices are equal for example:

  1. void call() {
  2. using int_types = std::tuple&lt;int8_t, uint8_t, int16_t, uint16_t, int32_t,
  3. uint32_t, int64_t, uint64_t&gt;;
  4. constexpr auto tsize = std::tuple_size_v&lt;int_types&gt;;
  5. []&lt;std::size_t... Is&gt;(std::index_sequence&lt;Is...&gt;) {
  6. ( // fold 1
  7. []&lt;size_t I, std::size_t... Js&gt;(std::integral_constant&lt;std::size_t, I&gt;,
  8. std::index_sequence&lt;Js...&gt;)
  9. {
  10. ( // fold 2:
  11. []&lt;std::size_t K, std::size_t L&gt;(
  12. std::integral_constant&lt;std::size_t, K&gt;,
  13. std::integral_constant&lt;std::size_t, L&gt;)
  14. {
  15. if constexpr(K != L) foo&lt;std::tuple_element_t&lt;K, int_types&gt;,
  16. std::tuple_element_t&lt;L, int_types&gt;&gt;();
  17. }(std::integral_constant&lt;std::size_t, I&gt;(),
  18. std::integral_constant&lt;std::size_t, Js&gt;()),
  19. ...);
  20. }(std::integral_constant&lt;std::size_t, Is&gt;(),
  21. std::make_index_sequence&lt;tsize&gt;()),
  22. ...);
  23. }(std::make_index_sequence&lt;tsize&gt;());
  24. }

Demo

huangapple
  • 本文由 发表于 2023年2月23日 22:24:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/75546120.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定