Как реализовать пользовательские потоковые манипуляторы, принимающие аргументы? - PullRequest
1 голос
/ 27 октября 2019

Например, мне нужен потоковый манипулятор, которому я могу передать uint8_t (unsigned char) и получить его вывод (например):

00 или 0f или a6.

Я знаю, что можно иметь потоковые манипуляторы без аргументов:

std::ostream &hex_format(std::ostream &out)
{
    out << std::hex << std::setfill('0') << std::setw(2);
    return out;
}

uint8_t x {15};
std::cout << hex_format << static_cast<int>(x); // should produce "0f"

, но как мне создать манипулятор, который принимает аргументы? Что-то вроде:

std::ostream &hex_format(std::ostream &out, uint8_t x)
{
    out << std::hex << std::setfill('0') << std::setw(2)
        << static_cast<int>(x);
    return out;
}

uint8_t x {15};
std::cout << hex_format(x); // (want to) produce "0f"

1 Ответ

0 голосов
/ 27 октября 2019

Используйте класс манипулятора:

struct hex_format {
    std::uint8_t number;

    hex_format(std::uint8_t x)
        :number{x}
    {
    }
};

Затем определите соответствующий оператор:

template <typename CharT, typename Traits>
decltype(auto) operator<<(std::basic_ostream<CharT, Traits>& os, hex_format rhs)
{
    return os << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>(x);
}

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

template <typename CharT, typename Traits>
decltype(auto) operator<<(std::basic_ostream<CharT, Traits>& os, hex_format rhs)
{
    auto flags = os.flags();
    os << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>(x);
    os.flags(flags);
    return os;
}
...