英文:
How to make a countl_zero() but for any type?
问题
template <typename T>
consteval int CountLeadingZeros(const T& DATA) {
T MASK{ 1 };
int BITSN{ sizeof(T) * CHAR_BIT },
LEADINGN{ 0 };
MASK <<= BITSN - 1;
for (int I = BITSN; I > 0; --I, ++LEADINGN, MASK >>= 1) {
if (DATA & MASK) {
break;
}
}
return LEADINGN;
}
constexpr int value = CountLeadingZeros<const int>(100);
错误:
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.
template <typename T>
consteval int CountLeadingZeros(const T& DATA) {
T MASK{ 1 };
int BITSN{ sizeof(T) * CHAR_BIT },
LEADINGN{ 0 };
MASK <<= BITSN - 1;
for (int I = BITSN; I > 0; I--, LEADINGN++, MASK >>= 1) {
if (DATA & MASK) {
break;
}
}
return LEADINGN;
}
But of cause it doesn't return a real const expression.
If you'll try to use it, there will be an error:
constexpr int value = CountLeadingZeros <const int> (100);
Error:
E3133 call to consteval function "fsm::CountLeadingZeros(const T &DATA) [with T=const int]" 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
以下是翻译好的代码部分:
一个更多的解决方案:
template <typename T, typename MASK_TYPE = typename remove_const<T>::type>
constexpr int CountLeadingZeros(const T & DATA) {
MASK_TYPE MASK{ 1 };
int BITSN{ sizeof(T) * CHAR_BIT },
LEADINGN{ 0 };
MASK <<= BITSN - 1;
for (int I = BITSN; I > 0; I--, LEADINGN++, MASK >>= 1) {
if (DATA & MASK) {
break;
}
}
return LEADINGN;
}
或者更简短的版本:
template <typename T, typename MASK_TYPE = typename remove_const<T>::type>
constexpr int LeadingN(const T& DATA) { // 返回位表示中前导零的数量
int BITSN{ sizeof(T) * CHAR_BIT }, I{ BITSN };
MASK_TYPE MASK{ 1u << BITSN - 1 };
for (; I && !(DATA & MASK); I--, MASK >>= 1) {}
return BITSN - I;
}
这是结果:
https://github.com/redmms/FineStream/tree/master
英文:
One more solution:
template <typename T, typename MASK_TYPE = typename remove_const<T>::type>
constexpr int CountLeadingZeros(const T & DATA) {
MASK_TYPE MASK{ 1 };
int BITSN{ sizeof(T) * CHAR_BIT},
LEADINGN{ 0 };
MASK <<= BITSN - 1;
for (int I = BITSN; I > 0; I--, LEADINGN++, MASK >>= 1) {
if (DATA & MASK) {
break;
}
}
return LEADINGN;
}
Or shorter version:
template <typename T, typename MASK_TYPE = typename remove_const<T>::type>
constexpr int LeadingN(const T& DATA) { // returns number of leading zeros in a bit representation
int BITSN{ sizeof(T) * CHAR_BIT }, I{ BITSN };
MASK_TYPE MASK{ 1u << BITSN - 1 };
for (; I && !(DATA & MASK); I--, MASK >>= 1) {}
return BITSN - I;
}
Here's the result:
https://github.com/redmms/FineStream/tree/master
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论