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

时间:2013-01-11 14:07:39

标签: c++ arrays casting c++11 compile-time

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

4 个答案:

答案 0 :(得分:9)

不,但您可以使用indices trick手动轻松完成,假设实施提供constexpr std::get(或等效constexpr重载{{1} }}):

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); } constexprget,则无法使用operator[],因为目前没有标准方式来访问数组元素{{1 }};您最好的选择是使用自己array的{​​{1}}扩展名实现。

建议在n3470中添加constexpr库添加到标准中。

答案 1 :(得分:2)

不是使用最常用的C ++编译器甚至无法编译的神秘模板代码,而是避免数字规范中的ungood冗余,而只是使用宏:

#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 :(得分:1)

你无法施放,但你可以复制:

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

答案 3 :(得分: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;
}