I'd like a way to take an arbitrary-size array of bytes and return a hex string. Specifically for logging packets sent over the net, but I use the equivalent function that takes a std::vector a lot. Something like this, probably a template?
std::string hex_str(const std::array<uint8_t,
???> array);
I've searched but the solutions all say "treat it as a C-style array" and I am specifically asking whether there's a way not to do that. I assume the reason this isn't in every single C FAQ is that it's impossible and if so can someone outline why?
I already have these overloads and the second one can be used for std::array by decaying into a C-style array, so please don't tell me how to do that.
std::string hex_str(const std::vector<uint8_t> &data);
std::string hex_str(const uint8_t *data, const size_t size);
(edit: vector is a reference in my code)
CodePudding user response:
If you know the size of the std::array
at compile time you can use a non type template parameter.
template<std::size_t N>
std::string hex_str( const std::array<std::uint8_t, N>& buffer )
{ /* Implementation */ }
int main( )
{
// Usage.
std::array<std::uint8_t, 5> bytes = { 1, 2, 3, 4, 5 };
const auto value{ hex_str( bytes ) };
}
Or you can just template the entire container (cut down on your overloads).
template<typename Container>
std::string hex_str( const Container& buffer )
{ /* Implementaion */ }
int main( )
{
// Usage.
std::array<std::uint8_t, 5> bytes = { 1, 2, 3, 4, 5 };
const auto value{ hex_str( bytes ) };
}
CodePudding user response:
You should consider writing the function to work with iterators, like standard algorithms do. Then you can use it with both std::vector
and std::array
inputs, eg:
template<typename Iter>
std::string hex_str(Iter begin, Iter end)
{
std::ostringstream output;
output << std::hex << std::setw(2) << std::setfill('0');
while(begin != end)
output << static_cast<unsigned>(*begin );
return output.str();
}
If you really want to avoid having to call begin()
/end()
on whatever container you pass in, you can define a helper to handle that for you, eg:
template<typename C>
std::string hex_str(const C &data) {
return hex_str(data.begin(), data.end());
}
Or, if you really wanted to, you can just flatten this all down into a single function, eg:
template <typename C>
std::string hex_str(const C& data)
{
std::ostringstream output;
output << std::hex << std::setw(2) << std::setfill('0');
for(const auto &elem : data)
output << static_cast<unsigned>(elem);
return output.str();
}