Is it possible to pass address of the first element of an array as argument to std::bit_cast
.
#include <bit>
#include <iostream>
struct A {
int a;
int b;
int c;
int d;
int e;
void print() {
std::cout << a << ", " << b << ", " << c << ", " << d << ", " << e << std::endl;
}
};
int main() {
char arr[20]{};
// arr is filled with some data
A a = std::bit_cast<A>(arr);
a.print();
const char* arrp = arr;
// doesn't compile
A b = std::bit_cast<A>(arrp);
b.print();
}
Error
<source>: In function 'int main()':
<source>:23:27: error: no matching function for call to 'bit_cast<A>(const char*&)'
23 | A b = std::bit_cast<A>(arrp);
| ~~~~~~~~~~~~~~~~^~~~~~
In file included from <source>:1:
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bit:81:5: note: candidate: 'template<class _To, class _From> constexpr _To std::bit_cast(const _From&) requires sizeof (_To) == sizeof (_From) && __is_trivially_copyable(_To) && __is_trivially_copyable(_From)'
81 | bit_cast(const _From& __from) noexcept
| ^~~~~~~~
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bit:81:5: note: template argument deduction/substitution failed:
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bit:81:5: note: constraints not satisfied
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bit: In substitution of 'template<class _To, class _From> constexpr _To std::bit_cast(const _From&) requires sizeof (_To) == sizeof (_From) && __is_trivially_copyable(_To) && __is_trivially_copyable(_From) [with _To = A; _From = const char*]':
<source>:23:27: required from here
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bit:81:5: required by the constraints of 'template<class _To, class _From> constexpr _To std::bit_cast(const _From&) requires sizeof (_To) == sizeof (_From) && __is_trivially_copyable(_To) && __is_trivially_copyable(_From)'
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bit:83:27: note: the expression 'sizeof (_To) == sizeof (_From) [with _To = A; _From = const char*]' evaluated to 'false'
83 | requires (sizeof(_To) == sizeof(_From))
| ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
Compiler returned: 1
Arrays are not pointers. std::bit_cast<A>(arr);
is correct.
arr
is passed by reference, and because std::bit_cast
has a const From&
parameter, From
deduces to char[20]
and you're effectively passing const char(&)[20]
, i.e. "reference to array of 20 const char
".
This is not the same as passing a pointer.
On the other hand, std::bit_cast<A>(arrp);
attempts to bit-cast a pointer (with size 8
, presumably) to an A
(with size 20
, presumably), and you cannot bit-cast between differently sized types.
The better approach here is to do type punning through std::memcpy
, which works because A
is trivially copyable and implicit-lifetime:
const char* arrp = arr;
A b;
std::memcpy(&b, arrp, sizeof(b));
b.print();
See also What is the modern, correct way to do type punning in C++?