“Cannot appear in a constant expression”意为“不能出现在常量表达式中”,我需要将其变成一个变量,为什么它不让我这样做?

7
string convert_binary_to_hex(string binary_value, int number_of_bits)
{
    bitset<number_of_bits> set(binary_value);   
    ostringstream result;
    result << hex << set.to_ulong() << endl;
    return result.str();
}

在上述方法中,我将二进制字符串转换为十六进制字符串。由于十六进制值是4位的,因此number_of_bits变量需要是4的倍数,因为binary_value在我编写的应用程序中可以从4位到256位不等。
如何使bitset接受可变大小?
我的导入:
#include <stdio.h>
#include <iostream>
#include <string>
#include <bitset>
#include <sstream>

因为编译器需要在编译时生成特定的位集类型。 - Nick
此外,请使用cstdio而不是stdio.h。 - Saurabh Manchanda
@Erik:输出字符串肯定包含与十六进制表示相对应的ASCII字符,因此在某种意义上,它“是十六进制”。 - Ben Voigt
6个回答

8

你不能这样做。像这样的模板参数需要在编译时知道,因为编译器将根据传递的值生成不同的代码。

在这种情况下,您可能希望遍历字符串并自己构建值,例如:

unsigned long result = 0;
for(int i = 0; i < binary_value.length(); ++i)
{
    result <<= 1;
    if (binary_value[i] != '0') result |= 1;
}

这也意味着您的结果比long类型更短,无法容纳256位的值 - 但是您的示例代码也无法容纳。您需要使用大数类型。


不需要大数,只需将其分成4位一组进行处理,这四位是彼此独立的。 - Ben Voigt
@Ben D'oh,是的,我不知怎么错过了它是全部为十六进制的事实 - 我一直在想十进制。如果是这样,您也可以写出每四个字符...我正要编码,但我看到您已经超越了我。+1 - Rup
@Dernalia 感谢您的接受!但是我错过了它应该是-to-hex而不是-to-decimal。我更喜欢Ben的答案比我的好。 - Rup

5

std::bitset的大小只能是编译时已知的常量表达式,因为它是一个整数模板参数。常量表达式包括整数字面值和/或用常量表达式初始化的常量整数变量。

例如:

std::bitset<4> q; //OK, 4 is a constant expression
const int x = 4;
std::bitset<x> qq; //OK, x is a constant expression, because it is const and is initialized with constant expression 4;
int y = 3;
const int z = y;
std::bitset<z> qqq; //Error, z isn't a constant expression, because even though it is const it is initialized with a non-constant expression

对于动态(不知道编译时大小)的大小,请使用std::vector<bool>boost::dynamic_bitset链接在这里),而不是使用普通数组。


我不明白在这里如何使用vector<bool>(虽然我从未使用过它)。 - UncleBens
@UncleBens:也许不是直接的问题,但是vector<bool>每个元素只保留一个位,因此会出现各种问题 :) - Armen Tsirunyan

3

您不能使用 std::bitset,因为它是一个模板,其大小必须在编译时指定。

您需要将 convert_binary_to_hex 单独作为一个模板。如果大小仅在运行时已知,则必须找到另一种解决方案。

template<size_t number_of_bits>
string convert_binary_to_hex(string binary_value)
{
   bitset<number_of_bits> set(binary_value);   
   ostringstream result;
   result << hex << set.to_ulong() << endl;
   return result.str();
}

2
如果您能在编译时知道大小,请将您的方法也变成一个模板,否则您需要使用 std::vector<bool>,该向量实际上是专门使用每个 bool 仅使用一位(即一个比特),但您需要使用 or 和位移来手动构建 ulong
//template version
template <size_t number_of_bits>
string convert_binary_to_hex(string binary_value) {
    bitset<number_of_bits> set(binary_value);
    ostringstream result;
    result << hex << set.to_ulong() << endl;
    return result.str();
} 

但是既然您已经假设ulong足够大来容纳位数,并且如果您的代码给出了太多的位数也不会有影响,那么为什么不将其大小设置为ulong呢?

//reuses ulong assumption
string convert_binary_to_hex(string binary_value) {
    bitset<sizeof(ulong)> set(binary_value);
    ostringstream result;
    result << hex << set.to_ulong() << endl;
    return result.str();
} 

或者您可以只有两个函数,一个用于执行 4 位数字的实际转换,另一个使用该函数来构建任意长度的数字:

string convert_nibble_to_hex(string binary_value) {
    bitset<4> set(binary_value);
    ostringstream result;
    result << hex << set.to_ulong() << endl;
    return result.str();
}

string convert_binary_to_hex(string binary_value) {
    //call convert_nibble_to_hex binary_value.length()/4 times
    //and concatenate results
}

2
据我记得,您可以使用模板来避免此问题:
template <size_t number_of_bits>
    string convert_binary_to_hex(string binary_value)
    {
        bitset<number_of_bits> set(binary_value);   
        ostringstream result;
        result << hex << set.to_ulong() << endl;
        return result.str();
    }

那么就像这样调用它:

convert_binary_to_hex<32>(12345678);

请注意,您仍然只能传递常量,但现在每次调用可以获取另一个常量 :)

1

你可以利用一个8位字符总是需要两个十六进制数字的事实。没有必要同时将整个字符串转换为比特序列,可以分别处理字符串元素。

string convert_octets_to_hex(string value)
{
    string result(2*value.size());
    for( int i = 0; i < value.size(); i++ ) {
        result[2*i]   = "0123456789abcdef"[(value[i] >> 4) & 0x0f];
        result[2*i+1] = "0123456789abcdef"[value[i] & 0x0f];
    }
    return result;
}

哦,我看到你有一个1位字符字符串。可以用同样的方式处理:

string convert_binary_to_hex(string binary_value, int number_of_bits = -1)
{
    if (number_of_bits < 0) number_of_bits = binary_value.size();
    string result((number_of_bits + 3) / 4, '\0');

    unsigned work;
    char* in = &binary_value[0];
    char* out = &result[0];
    if (number_of_bits & 3) {
        work = 0;
        while (number_of_bits & 3) {
            work <<= 1;
            work |= *(in++) & 1;
            number_of_bits--;
        }
        *(out++) = "0123456789abcdef"[work];
    }
    while (number_of_bits) {
        work = ((in[0] & 1) << 3) | ((in[1] & 1) << 2) | ((in[2] & 1) << 1) | (in[3] & 1);
        in += 4;
        *(out++) = "0123456789abcdef"[work];
        number_of_bits -= 4;
    }
    return result;
}

编辑:修复了一些错误,添加了演示


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接