繁体   English   中英

C++ SFINAE 双嵌套 initializer_list 与可变参数模板构造函数

[英]C++ SFINAE double nested initializer_list vs. variadic template constructor

问题

我正在编写一个包含VectorMatrix类的小型数学库。 我想通过严格的初始化规则来方便地初始化这些类的对象。

Vector class 构造函数已经按我的预期工作。 它受到限制,只接受正确的大小N ,除此之外,所有 arguments 都是同一类型(见下文)。

Vector

template <std::size_t N, typename T>
class Vector{
  public:
    template <typename... TArgs,
            std::enable_if_t<
                sizeof...(TArgs) == N &&
                    (std::is_same_v<T, std::remove_reference_t<TArgs>> && ...),int> = 0>
    Vector(TArgs &&... args) : data_{std::forward<TArgs>(args)...} {}

    // ...

  private:
    std::array<T,N> data;
}

示例初始化(有效,受限制)

Vector<3,int> v{1,2,3}

Matrix

template <std::size_t N, std::size_t M, typename T>
class Matrix{
  public:
    /* put restriction rules here */
    Matrix(std::initializer_list<std::initializer_list<T>> lst) {
      int i = 0;
      int j = 0;
      for (const auto &l : lst) {
        for (const auto &v : l) {
          data[i][j] = v;
          ++j;
        }
        j = 0;
        ++i;
      }
    }

    // ...

  private:
    std::array<Vector<M, T>, N> data;
}

示例初始化 1(有效,不受限制)

Matrix<2,3,int> m{ {1,2,3}, {4,5,6} }

示例初始化 2(编译,但不应该!!)

Matrix<2,3,int> m{ {1,'a',3}, {4,5,6,7,8,9} }

问题

我无法使用可变参数模板为双嵌套初始化实现Matrix class 构造函数,因此我使用了嵌套的std::initializer_list (来自这篇文章)。 它可以工作,但我希望对这个构造函数有与Vector class 相同的限制。

我怎样才能做到这一点?

  • 列表大小必须为 N(行)
  • 列表列表大小必须始终为 M(列)
  • 封装的值类型必须始终为 T

附加信息

关于这里的这篇文章... ::std::initializer_list vs variadic templates我可以说我真的不喜欢使用 initializer_list 或 variadic 模板。 在这种情况下,任何一个看起来都很好,但据我所知,在编译时获取std::initializer_list的大小有点困难。

您可以简单地使Matrix采用 2D 数组引用,如下所示:

Matrix(T const (&m)[N][M])

这只会在您指定的条件下编译,并且调整您的代码的 rest 也很容易。 您可以应用相同的原理来简化Vector

要获得所需的语法,您可以这样做:

template <typename ... Us,
          std::enable_if_t<sizeof...(Us) == N && (std::is_same_v<Us, T> && ...), int> = 0>
Matrix(const Us (&... rows)[M]) {
    // ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM