如何创建一个`countl_zero()`函数,但适用于任何类型?

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

How to make a countl_zero() but for any type?

问题

  1. template <typename T>
  2. consteval int CountLeadingZeros(const T& DATA) {
  3. T MASK{ 1 };
  4. int BITSN{ sizeof(T) * CHAR_BIT },
  5. LEADINGN{ 0 };
  6. MASK <<= BITSN - 1;
  7. for (int I = BITSN; I > 0; --I, ++LEADINGN, MASK >>= 1) {
  8. if (DATA & MASK) {
  9. break;
  10. }
  11. }
  12. return LEADINGN;
  13. }
  1. constexpr int value = CountLeadingZeros<const int>(100);

错误:

  1. E3133 调用到 consteval 函数"fsm::CountLeadingZeros(const T &DATA) [with T=const int]"未生成有效的常量表达式

另一方面,C++20的countl_zero()函数完美工作并返回constexpr。但它只能用于uint8_t以外的类型。

请帮助我解决这个E3133错误。我如何让我的函数在编译时工作?

英文:

I use in my project such a function for counting leading zeros, the aim for it is to work with any non container type and to return a constant expression, so that I could use it's results for other templates.

  1. template &lt;typename T&gt;
  2. consteval int CountLeadingZeros(const T&amp; DATA) {
  3. T MASK{ 1 };
  4. int BITSN{ sizeof(T) * CHAR_BIT },
  5. LEADINGN{ 0 };
  6. MASK &lt;&lt;= BITSN - 1;
  7. for (int I = BITSN; I &gt; 0; I--, LEADINGN++, MASK &gt;&gt;= 1) {
  8. if (DATA &amp; MASK) {
  9. break;
  10. }
  11. }
  12. return LEADINGN;
  13. }

But of cause it doesn't return a real const expression.
If you'll try to use it, there will be an error:

  1. constexpr int value = CountLeadingZeros &lt;const int&gt; (100);

Error:

  1. E3133 call to consteval function &quot;fsm::CountLeadingZeros(const T &amp;DATA) [with T=const int]&quot; did not produce a valid constant expression

On the other hand C++20 countl_zero() works perfect and returns constexpr. But it can not work with anything except uint8_t.

Help me please to fight and win this E3133 error. How could I make my function working in compile time?

答案1

得分: 0

不要将const int作为模板参数传递。将其替换为int。目前,MASK被声明为const int MASK = 1,然后您尝试修改它,这显然是行不通的。否则,函数应该是常量可求值的。

英文:

Don't pass const int as the template argument. Replace it with just int. Currently, MASK gets declared as const int MASK = 1, and then you try to modify it, which obviously doesn't work. Otherwise, the function should be constant-evaluatable

答案2

得分: 0

以下是翻译好的代码部分:

  1. 一个更多的解决方案:
  2. template <typename T, typename MASK_TYPE = typename remove_const<T>::type>
  3. constexpr int CountLeadingZeros(const T & DATA) {
  4. MASK_TYPE MASK{ 1 };
  5. int BITSN{ sizeof(T) * CHAR_BIT },
  6. LEADINGN{ 0 };
  7. MASK <<= BITSN - 1;
  8. for (int I = BITSN; I > 0; I--, LEADINGN++, MASK >>= 1) {
  9. if (DATA & MASK) {
  10. break;
  11. }
  12. }
  13. return LEADINGN;
  14. }
  15. 或者更简短的版本:
  16. template <typename T, typename MASK_TYPE = typename remove_const<T>::type>
  17. constexpr int LeadingN(const T& DATA) { // 返回位表示中前导零的数量
  18. int BITSN{ sizeof(T) * CHAR_BIT }, I{ BITSN };
  19. MASK_TYPE MASK{ 1u << BITSN - 1 };
  20. for (; I && !(DATA & MASK); I--, MASK >>= 1) {}
  21. return BITSN - I;
  22. }
  23. 这是结果:
  24. https://github.com/redmms/FineStream/tree/master
英文:

One more solution:

  1. template &lt;typename T, typename MASK_TYPE = typename remove_const&lt;T&gt;::type&gt;
  2. constexpr int CountLeadingZeros(const T &amp; DATA) {
  3. MASK_TYPE MASK{ 1 };
  4. int BITSN{ sizeof(T) * CHAR_BIT},
  5. LEADINGN{ 0 };
  6. MASK &lt;&lt;= BITSN - 1;
  7. for (int I = BITSN; I &gt; 0; I--, LEADINGN++, MASK &gt;&gt;= 1) {
  8. if (DATA &amp; MASK) {
  9. break;
  10. }
  11. }
  12. return LEADINGN;
  13. }

Or shorter version:

  1. template &lt;typename T, typename MASK_TYPE = typename remove_const&lt;T&gt;::type&gt;
  2. constexpr int LeadingN(const T&amp; DATA) { // returns number of leading zeros in a bit representation
  3. int BITSN{ sizeof(T) * CHAR_BIT }, I{ BITSN };
  4. MASK_TYPE MASK{ 1u &lt;&lt; BITSN - 1 };
  5. for (; I &amp;&amp; !(DATA &amp; MASK); I--, MASK &gt;&gt;= 1) {}
  6. return BITSN - I;
  7. }

Here's the result:
https://github.com/redmms/FineStream/tree/master

huangapple
  • 本文由 发表于 2023年7月20日 19:34:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76729428.html
匿名

发表评论

匿名网友

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

确定