在编译时将std :: array转换为另一种数据类型?

Vin*_*ent 7 c++ arrays casting compile-time c++11

在编译时,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;
}
Run Code Online (Sandbox Code Playgroud)

eca*_*mur 9

不,但你可以使用索引技巧相当容易地手工完成,假设实现提供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);
}
Run Code Online (Sandbox Code Playgroud)

如果您的实现没有提供,constexpr get或者operator[]您不能使用,array因为没有当前的标准方法来访问数组元素constexpr; 您最好的选择是使用您自己arrayconstexpr扩展实现.

constexpr库添加是提出了除标准n3470.


Vin*_*ent 3

我找到了一个非常简单的解决方案,只有一个可变参数函数:

#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;
}
Run Code Online (Sandbox Code Playgroud)