c++ - 在其他类中实现类似 std::array 的构造函数

标签 c++ arrays c++11 variadic-templates

在我使用过的所有现代 C++ 编译器中,以下是合法的:

std::array<float, 4> a = {1, 2, 3, 4};

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

#include <array>
#include <cstddef>

template<std::size_t n>
class float_vec
{
private:
  std::array<float, n> underlying_array;

public:
  template<typename... Types>
  float_vec(Types... args)
    : underlying_array{{args...}}
  {
  }
};

int main()
{
  float_vec<4> v = {1, 2, 3, 4}; // error here
}

当像上面那样使用 int 文字时,编译器会提示它无法将 int 隐式转换为 float。不过,我认为它在 std::array 示例中有效,因为给出的值是已知在 float 域内的编译时常量。另一方面,在这里,可变参数模板使用 int 作为参数类型,并且转换发生在构造函数的初始化列表中,其中的值在编译时是未知的。

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

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

有什么想法吗?我想要的东西甚至可以用 C++11 实现吗?有什么新的 C++14 提议可以解决这个问题吗?

最佳答案

一个小技巧是使用构造函数继承。只需让您的类派生自另一个具有您想要的参数包的类。

template <class T, std::size_t N, class Seq = repeat_types<N, T>>
struct _array_impl;

template <class T, std::size_t N, class... Seq>
struct _array_impl<T, N, type_sequence<Seq...>>
{
    _array_impl(Seq... elements) : _data{elements...} {}
    const T& operator[](std::size_t i) const { return _data[i]; }

    T _data[N];
};


template <class T, std::size_t N>
struct array : _array_impl<T, N>
{
    using _array_impl<T, N>::_array_impl;
};

int main() {
    array<float, 4> a {1, 2, 3, 4};
    for (int i = 0; i < 4; i++)
        std::cout << a[i] << std::endl;
    return 0;
}

这是 repeat_types 实用程序的示例实现。此示例使用对数模板递归,与线性递归相比,这种递归的实现不太直观。

template <class... T>
struct type_sequence
{
    static constexpr inline std::size_t size() noexcept { return sizeof...(T); }
};


template <class, class>
struct _concatenate_sequences_impl;
template <class... T, class... U>
struct _concatenate_sequences_impl<type_sequence<T...>, type_sequence<U...>>
    { using type = type_sequence<T..., U...>; };
template <class T, class U>
using concatenate_sequences = typename _concatenate_sequences_impl<T, U>::type;


template <std::size_t N, class T>
struct _repeat_sequence_impl
    { using type = concatenate_sequences<
        typename _repeat_sequence_impl<N/2, T>::type,
        typename _repeat_sequence_impl<N - N/2, T>::type>; };
template <class T>
struct _repeat_sequence_impl<1, T>
    { using type = T; };
template <class... T>
struct _repeat_sequence_impl<0, type_sequence<T...>>
    { using type = type_sequence<>; };
template <std::size_t N, class... T>
using repeat_types = typename _repeat_sequence_impl<N, type_sequence<T...>>::type;

关于c++ - 在其他类中实现类似 std::array 的构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21342545/

相关文章:

c++ - 具有类默认值的模板参数

c++ - 为什么拷贝可以在c++中替换?

c++ - 为什么 std::set 似乎强制使用 const_iterator?

unordered_map 上的 C++ 未定义行为作为基于范围的 for 循环中的右值

c++ - 类内初始化顺序与构造函数初始化列表

c++ - 保存 C++ 预处理器宏的原始值

java - 访问 ArrayList 中每个数组的第一个元素并对所有元素求平均值

arrays - 如何在 Perl 中正确替换哈希数组中的值?

arrays - SwiftUI @State 数组不更新在 init() 期间附加的值

c++ - 无法将 std::packaged_task 移动到 lambda 中