Привести std :: array к другому типу данных во время компиляции?

Есть ли в C ++ 11 способ приведения массива одного типа к другому типу данных во время компиляции:

#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;
}

7

Решение

Нет, но вы можете сделать это вручную довольно легко, используя трюк с индексами, при условии, что реализация обеспечивает constexpr std::get (или эквивалентно constexpr перегрузка 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);
}

Если ваша реализация не обеспечивает constexpr get или же operator[], вы не можете использовать array так как нет текущего стандартного способа доступа к элементам массива constexpr; Лучше всего использовать собственную реализацию array с constexpr расширения.

constexpr В дополнение к стандарту предлагаются дополнения к библиотекам. n3470.

9

Другие решения

Вместо бесполезного беспорядка загадочного кода шаблона, который в настоящее время даже не компилируется с наиболее часто используемым компилятором C ++, и избегая плохой избыточности в числовых спецификациях, просто используйте макрос:

#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...
}

Это такие вещи, в которых хорошо справляются макросы.

Просто убедитесь, что минимизирована возможность конфликта имен, используя имя макроса в верхнем регистре и, возможно, какой-нибудь собственный префикс.


Общий совет: не будь слишком умным, будь проще.

Имейте в виду, кто-то должен поддерживать это позже.

2

Вы не можете разыграть, но вы можете скопировать:

static constexpr std::array<double, 3> darray{{1.5, 2.5, 3.5}};
std::array<int, 3> iarray;

std::copy(begin(darray), end(darray), begin(iarray));

к несчастью iarray не может быть constexpr больше в этом случае.

1

Я нашел очень простое решение с одной переменной функцией:

#include <iostream>
#include <array>
#include <type_traits>

template<typename Type, typename OtherType, std::size_t Size, typename... Types, class = typename std::enable_if<sizeof...(Types) != Size>::type>
constexpr std::array<Type, Size> convert(const std::array<OtherType, Size> source, const Types... data);

template<typename Type, typename OtherType, std::size_t Size, typename... Types, class = typename std::enable_if<sizeof...(Types) == Size>::type, class = void>
constexpr std::array<Type, Size> convert(const std::array<OtherType, Size> source, const Types... data);

template<typename Type, typename OtherType, std::size_t Size, typename... Types, class>
constexpr std::array<Type, Size> convert(const std::array<OtherType, Size> source, const Types... data)
{
return convert<Type>(source, data..., static_cast<const Type>(source[sizeof...(data)]));
}

template<typename Type, typename OtherType, std::size_t Size, typename... Types, class, class>
constexpr std::array<Type, Size> convert(const std::array<OtherType, Size> source, const Types... data)
{
return std::array<Type, Size>{{data...}};
}

int main()
{
static constexpr std::array<double, 3> darray{{1., 2., 3.}};
static constexpr std::array<int, 3> iarray = convert<int>(darray);
std::cout<<(std::integral_constant<int, iarray[2]>())<<std::endl;
return 0;
}
1
По вопросам рекламы [email protected]