解包枚举的可变参数包

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

Unpacking Variadic Parameter Pack of Enums

问题

以下是您要求的翻译:

  1. 更新:已编辑以修复工作示例中的编译问题。
  2. 我想要做类似以下的事情,以便该函数可以接受枚举类实例的列表或保存它们的结构体,但是“auto myFunc2<EList<Types...>>”的定义失败,出现“期望常数而不是E::A”的错误。
  3. ```cpp
  4. #include <cstdint>
  5. #include <iostream>
  6. enum class E { A = 0, B = 1 };
  7. template <E... Types> struct tl2 {};
  8. using my_list_2 = tl2<E::A>;
  9. template <E... Types>
  10. auto myFunc2 = [] {
  11. std::cout << "Size: " << sizeof...(Types) << std::endl;
  12. };
  13. template <template <E...> typename EList, E... Types>
  14. auto myFunc2<EList<Types...>> = [] {
  15. std::cout << "Size: " << sizeof...(Types) << std::endl;
  16. };
  17. int main() {
  18. myFunc2<E::A, E::B>(); // 此调用打印类型列表的大小
  19. // 当注释掉myFunc2<Elist<Types..>>时可以正常工作
  20. // myFunc2<my_list_2>(); // 这会导致错误
  21. }

如果将此转换为通用类型,则一切都会编译并按预期工作。例如:

  1. #include <cstdint>
  2. #include <iostream>
  3. template <typename ... Types> struct tl
  4. {
  5. };
  6. using my_list = tl <int, float, uint64_t>;
  7. template <typename ... Types>
  8. static constexpr auto myFunc2 = [] {
  9. std::cout << "Size: " << sizeof...(Types) << std::endl;
  10. };
  11. template <template <class...> class TL, typename ... Types>
  12. static constexpr auto myFunc2<TL<Types...>> = [] {
  13. std::cout << "Size: " << sizeof...(Types) << std::endl;
  14. };
  15. int main() {
  16. myFunc2<int, uint64_t, bool, uint16_t>();
  17. myFunc2<my_list>();
  18. }

这里发生了什么?枚举类在模板中的处理是否存在限制?

希望这可以帮助您理解问题所在。如果您需要更多信息或有其他问题,请随时提问。

英文:

Update: Edited to fix compilation in working example.

I want to do something like the following so the function can take in both a list of the enum class instances or a struct that holds them, but the definition of auto myFunc2&lt;EList&lt;Types...&gt;&gt; fails with expected a constant not E::A

  1. #include &lt;cstdint&gt;
  2. #include &lt;iostream&gt;
  3. enum class E {A = 0, B=1};
  4. template&lt;E... Types&gt; struct tl2 {};
  5. using my_list_2 = tl2&lt;E::A&gt;;
  6. template &lt;E ... Types&gt;
  7. auto myFunc2 = [] {
  8. std::cout &lt;&lt; &quot;Size: &quot; &lt;&lt; sizeof...(Types) &lt;&lt; std::endl;
  9. };
  10. template &lt;template&lt;E...&gt; typename EList, E... Types&gt;
  11. auto myFunc2&lt;EList&lt;Types...&gt;&gt; = [] {
  12. std::cout &lt;&lt; &quot;Size: &quot; &lt;&lt; sizeof...(Types) &lt;&lt; std::endl;
  13. };
  14. int main() {
  15. myFunc2&lt;E::A, E::B&gt;(); // This call prints size of typelist
  16. //Works when myFunc2&lt;Elist&lt;Types..&gt;&gt; is commented out
  17. //myFunc2&lt;my_list_2&gt;(); //This breaks
  18. }

If we convert this to general types then everything compiles and works as expected. For example:

  1. #include &lt;cstdint&gt;
  2. #include &lt;iostream&gt;
  3. template &lt; typename ... Types &gt; struct tl
  4. {
  5. };
  6. using my_list = tl &lt;int, float, uint64_t&gt;;
  7. template &lt;typename ... Types&gt;
  8. static constexpr auto myFunc2 = [] {
  9. std::cout &lt;&lt; &quot;Size: &quot; &lt;&lt; sizeof...(Types) &lt;&lt; std::endl;
  10. };
  11. template &lt;template&lt;class...&gt; class TL, typename ... Types&gt;
  12. static constexpr auto myFunc2&lt;TL&lt;Types...&gt;&gt; = [] {
  13. std::cout &lt;&lt; &quot;Size: &quot; &lt;&lt; sizeof...(Types) &lt;&lt; std::endl;
  14. };
  15. int main() {
  16. myFunc2&lt;int,uint64_t,bool,uint16_t&gt;();
  17. myFunc2&lt;my_list&gt;();
  18. }

What is going on here? Is there a limitation in how enum classes can be handled as templates?

答案1

得分: 2

  1. 真正的函数模板可以做到这一点(通常需要额外的辅助来推导参数包):
  2. ```cpp
  3. template <typename... Types>
  4. void myFunc2() {
  5. std::cout << "Size: " << sizeof...(Types) << std::endl;
  6. }
  7. namespace detail {
  8. template <template<typename...> typename EList, typename... Types>
  9. void myFunc2(EList<Types...>) {
  10. std::cout << "Size: " << sizeof...(Types) << std::endl;
  11. }
  12. }
  13. template <typename EList>
  14. void myFunc2() {
  15. detail::myFunc2(EList());
  16. }

这种方法使得“一个模板”能够接受不同种类的模板参数,因为具有错误种类的模板参数的模板将在重载解析过程中被忽略。

  1. <details>
  2. <summary>英文:</summary>
  3. True **function** templates can do this (with the usual extra helper for deducing a pack):

template <E ... Types>
void myFunc2() {
std::cout << "Size: " << sizeof...(Types) << std::endl;
}

namespace detail {
template <template<E...> typename EList, E... Types>
void myFunc2(EList<Types...>>) {
std::cout << "Size: " << sizeof...(Types) << std::endl;
}
}

template <typename EList>
void myFunc2() {
detail::myFunc2(EList());
}

  1. This approach allows one template to accept template arguments of different **kinds** because the templates with the wrong kinds of template parameters will simply be ignored during overload resolution.
  2. </details>

huangapple
  • 本文由 发表于 2023年6月16日 04:15:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76485225.html
匿名

发表评论

匿名网友

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

确定