Печать int в двоичном формате с фиксированной длиной

Я перегружаю << для печати пользовательских объектов (в этом случае экземпляры пользовательского класса Vertex). Как часть этого, я хочу напечатать данное целое число в двоичном виде. Я предпочел бы по многим причинам std::bitset вместо того, чтобы запускать цикл for, но проблема, с которой я сталкиваюсь, заключается в том, что у меня есть определенный размер каждого двоичного файла, который зависит от экземпляра. Вот фрагмент:

std::ostream &
operator<< (std::ostream& os, const Vertex& V) {
    os << "(" << std::bitset<4>(V.signature()) << ") :";
    for (int e=2; e<V.degree(); ++e) {
        os << " [" << e << "]=" << V.neighbor(e) << " ";
    }
    return os;
}

Вместо 4Я очень хочу поставить size_t это зависит от V, Например, вот что я попробовал:

std::ostream &
operator<< (std::ostream& os, const Vertex& V) {
    size_t B = V.degree()-1;
    os << "(" << std::bitset<B>(V.signature()) << ") :";
    for (int e=2; e<V.degree(); ++e) {
        os << " [" << e << "]=" << V.neighbor(e) << " ";
    }
    return os;
}

Ошибка гласит: "Нетипичный аргумент шаблона не является константным выражением". Есть ли способ исправить это без жесткого кодирования параметра? Это не то, что будет известно во время компиляции.

3 ответа

Как насчет простой функции:

string bin_format(int_type value, size_t len);

который вы затем пишете в поток, используя

out << bin_format(v.signature(), v.degree()-1);

Все, что выходит за рамки этого, нарушает принцип KISS и должно быть тщательно обосновано. Например, если вам удастся повторить это так часто, что динамическое распределение в string вызывает проблемы, вы можете либо написать функцию, принимающую поток и параметры, и записать отдельные биты в поток, либо вы можете вернуть прокси с перегруженным operator<< где этот оператор выполняет форматирование и потоковую передачу. Кстати, вы также можете превратить эту функцию в шаблон, основанный на целочисленном типе, так что вы можете по крайней мере поставить максимальное количество нужных вам битов.

Это полный взлом, так что я надеюсь на что-то лучшее, но, похоже, работа сделана на данный момент. Улучшения приветствуются!

std::ostream &
operator<< (std::ostream& os, const Vertex& V) {
    std::string bin = std::bitset<16>(V.signature()).to_string();
    bin.erase(bin.begin(),bin.end()-V.degree()+1);
    os << "(" << bin << ") :";
    for (int e=2; e<V.degree(); ++e) {
        os << " [" << e << "]=" << V.neighbor(e) << " ";
    }
    return os;
}

Поскольку нет возможности использовать std::bitset<> с параметром времени выполнения, вы, вероятно, должны написать свой собственный класс / функцию для отображения битов. Вот пример такого класса, который перегружает вставку потока operator<<:

// Display bits at runtime (cannot use std::bitset<> in this case)

#include <algorithm> // for std::reverse
#include <cstddef>   // for std::size_t
#include <iostream>
#include <string>

template<typename T>
class disp_bitset
{
    std::size_t _size;
    T _n;
public:
    explicit disp_bitset(std::size_t size, T n): _size(size), _n(n) {}
    friend std::ostream& operator<<(std::ostream& os, const disp_bitset& rhs)
    {
        T tmp = rhs._n;
        std::string aux;
        for (std::size_t i = 0; i < rhs._size; ++i)
        {
            aux += (tmp & 0x01) + '0';
            tmp = tmp >> 1;
        }
        std::reverse(aux.begin(), aux.end());
        return os << aux;
    }
};

int main()
{
    disp_bitset<std::size_t> x(8, 41); // size_t 41 on 8 bits
    std::cout << x << std::endl;
    std::cout << disp_bitset<char>(16, 'a'); // char 'a' on 16 bits
}
Другие вопросы по тегам