template<typename T>
std::string bit_representation(T &&type) {
uint8_t data[sizeof(T)];
if constexpr (std::is_copy_constructible_v<T>) {
T tmp(type);
std::memcpy(&data, &tmp, sizeof(T));
} else if (std::is_move_constructible_v<T>) {
T tmp(std::move(type));
std::memcpy(&data, &tmp, sizeof(T));
}
auto get_byte_repr = [](uint8_t byte) -> std::string {
std::string s;
constexpr size_t byte_size = sizeof(uint8_t) * 8;
s.resize(byte_size);
for (int i = byte_size - 1; i >= 0; --i) {
s[i] = ((byte & 1) == 1) ? '1' : '0';
byte >>= 1;
}
return s;
};
std::string result;
for (int i = sizeof(T) - 1; i >= 0; --i) {
result += get_byte_repr(data[i]);
}
return result;
}
I wrote simple bit_representation function, for simple types all good but i want to write uniform template function for pass std::initializer_list<T> too.
uint8_t u8 = 0xAF;
std::cout << bit_representation(u8) << std::endl; // 10101111 ok
std::cout << bit_representation((uint8_t) 0xAF) << std::endl; // 10101111 ok
std::cout << bit_representation((short) 0xAF) << std::endl; // 0000000010101111 ok
double d = 2.56;
// 0100000000000100011110101110000101000111101011100001010001111011 = d its ok iee-754
std::cout << bit_representation(d) << std::endl;
#pragma pack(1)
struct {
bool c = true;
int a = 0x00FF00FF;
} name;
#pragma pop()
// 0000000011111111000000001111111100000001 // really ok
std::cout << bit_representation(name) << std::endl; // ok
std::cout << bit_representation(true) << std::endl; // 00000001 ok
std:cout << bit_representation({1,2,3,4}) << std::endl; /* error candidate template ignored: couldn't infer template argument 'T'
std::string bit_representation(T &&type) {*/
But bit_representation({1,2,3,4}) not working..
I thing need write SFINAE wrapper for compile time detecting if type is initializer_list<T>.
I expecting bit_representation({1,2,3,4}) -> std::initializer_list to memory repr ->
00000000000000000000000000000001000000000000000000000000000000100000000000000000000000000000001100000000000000000000000000000100
How to deduce std::inititalizer_list parameters and write special logic for this.
std::initializer_listis somewhat special. In particular (from cppreference):bit_representation({1,2,3,4})is none of this.{1,2,3,4}is not astd::initializer_list. Only in certain contexts{1,2,3,4}causes astd::initializer_listto be automatically constructed. In all other contexts{1,2,3,4}has no type that could be deduced.You can call the function with a
std::initializer_listlike this:Moreover, consider that any object can be viewed as an array of bytes. No copying to an array is needed. This is due to the exception for
char,byteandunsigned charfor strict aliasing, as explained here: https://en.cppreference.com/w/cpp/language/reinterpret_cast. It is also unclear why your function does not use its argumenttype(rather misleading name) directly but makes another unnecessary copytmpbefore copying to the array.This might give you a better start (untested):