c – 在其他类中实现std :: array-like构造函数

前端之家收集整理的这篇文章主要介绍了c – 在其他类中实现std :: array-like构造函数前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在我使用的所有现代C编译器中,以下是合法的:
  1. std::array<float,4> a = {1,2,3,4};

我正在尝试创建具有类似构造语义的我自己的类,但我遇到了一个恼人的问题.考虑以下尝试:

  1. #include <array>
  2. #include <cstddef>
  3.  
  4. template<std::size_t n>
  5. class float_vec
  6. {
  7. private:
  8. std::array<float,n> underlying_array;
  9.  
  10. public:
  11. template<typename... Types>
  12. float_vec(Types... args)
  13. : underlying_array{{args...}}
  14. {
  15. }
  16. };
  17.  
  18. int main()
  19. {
  20. float_vec<4> v = {1,4}; // error here
  21. }

当使用上面的int文字时,编译器抱怨它不能隐式地将int转换为float.我认为它在std :: array示例中有效,因为给出的值是已知在float域内的编译时常量.另一方面,可变参数模板使用int作为参数类型,转换发生在构造函数的初始化列表中,其中值在编译时是未知的.

我不想在构造函数中进行显式强制转换,因为即使它们不能用float表示,它也允许所有数值.

我能想到得到我想要的唯一方法是以某种方式具有可变数量的参数,但具有特定类型(在这种情况下,我想要浮动).我知道std :: initializer_list,但我希望能够在编译时强制执行参数的数量.

有任何想法吗? C 11是我想要的吗?为C 14提出的任何新建议都能解决这个问题吗?

解决方法

一个小技巧是使用构造函数继承.只需让你的类派生自另一个具有一包你想要的参数的类.
  1. template <class T,std::size_t N,class Seq = repeat_types<N,T>>
  2. struct _array_impl;
  3.  
  4. template <class T,class... Seq>
  5. struct _array_impl<T,N,type_sequence<Seq...>>
  6. {
  7. _array_impl(Seq... elements) : _data{elements...} {}
  8. const T& operator[](std::size_t i) const { return _data[i]; }
  9.  
  10. T _data[N];
  11. };
  12.  
  13.  
  14. template <class T,std::size_t N>
  15. struct array : _array_impl<T,N>
  16. {
  17. using _array_impl<T,N>::_array_impl;
  18. };
  19.  
  20. int main() {
  21. array<float,4> a {1,4};
  22. for (int i = 0; i < 4; i++)
  23. std::cout << a[i] << std::endl;
  24. return 0;
  25. }

以下是repeat_types实用程序的示例实现.此示例使用对数模板递归,与线性递归相比,它实现起来不太直观.

  1. template <class... T>
  2. struct type_sequence
  3. {
  4. static constexpr inline std::size_t size() noexcept { return sizeof...(T); }
  5. };
  6.  
  7.  
  8. template <class,class>
  9. struct _concatenate_sequences_impl;
  10. template <class... T,class... U>
  11. struct _concatenate_sequences_impl<type_sequence<T...>,type_sequence<U...>>
  12. { using type = type_sequence<T...,U...>; };
  13. template <class T,class U>
  14. using concatenate_sequences = typename _concatenate_sequences_impl<T,U>::type;
  15.  
  16.  
  17. template <std::size_t N,class T>
  18. struct _repeat_sequence_impl
  19. { using type = concatenate_sequences<
  20. typename _repeat_sequence_impl<N/2,T>::type,typename _repeat_sequence_impl<N - N/2,T>::type>; };
  21. template <class T>
  22. struct _repeat_sequence_impl<1,T>
  23. { using type = T; };
  24. template <class... T>
  25. struct _repeat_sequence_impl<0,type_sequence<T...>>
  26. { using type = type_sequence<>; };
  27. template <std::size_t N,class... T>
  28. using repeat_types = typename _repeat_sequence_impl<N,type_sequence<T...>>::type;

猜你在找的C&C++相关文章