Is there a way in C++11 to cast an array of one type to another data type at compile-time :
#include <iostream>
#include <array>
#include <type_traits>
int main()
{
static constexpr std::array<double, 3> darray{{1.5, 2.5, 3.5}};
static constexpr std::array<int, 3> iarray(darray); // not working
// Is there a way to cast an array to another data type ?
return 0;
}
No, but you can do it by hand fairly easily using the indices trick, assuming the implementation provides constexpr
std::get
(or equivalently a constexpr
overload of operator[]
):
#include <iostream>
#include <array>
#include <type_traits>
// http://loungecpp.wikidot.com/tips-and-tricks%3aindices
template <std::size_t... Is>
struct indices {};
template <std::size_t N, std::size_t... Is>
struct build_indices: build_indices<N-1, N-1, Is...> {};
template <std::size_t... Is>
struct build_indices<0, Is...>: indices<Is...> {};
template<typename T, typename U, size_t i, size_t... Is>
constexpr auto array_cast_helper(
const std::array<U, i> &a, indices<Is...>) -> std::array<T, i> {
return {{static_cast<T>(std::get<Is>(a))...}};
}
template<typename T, typename U, size_t i>
constexpr auto array_cast(
const std::array<U, i> &a) -> std::array<T, i> {
// tag dispatch to helper with array indices
return array_cast_helper<T>(a, build_indices<i>());
}
int main() {
static constexpr std::array<double, 3> darray{{1.5, 2.5, 3.5}};
static constexpr std::array<int, 3> iarray = array_cast<int>(darray);
}
If your implementation doesn't provide constexpr
get
or operator[]
, you can't use array
as there's no current standard way to access array elements constexpr
; your best bet is to use your own implementation of array
with the constexpr
extensions.
The constexpr
library additions are proposed for addition to the standard in n3470.
Instead of an unmaintainable mess of cryptic template code that won't even currently compile with the most commonly used C++ compiler, and avoiding ungood redundancy in the number specs, simply use a macro:
#include <iostream>
#include <array>
#include <type_traits>
#define MY_VALUES( T ) {T(1.5), T(2.5), T(3.5)}
int main()
{
static constexpr std::array<double, 3> darray = { MY_VALUES( double ) };
static constexpr std::array<int, 3> iarray = { MY_VALUES( int ) };
// Whatever...
}
This is the kind of stuff macros are good at.
Just make sure to minimize the possibility of name collision by using an all uppercase macro name, and maybe some custom prefix.
General advice: don't be too clever, keep it simple.
Keep in mind, someone has to maintain it later.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With