c++ - 我如何在我的矩阵类中获得此功能?

标签 c++ class c++11 templates initializer-list

#include <iostream>
#include <array>

template<typename T, std::size_t R, std::size_t C>
class matrix
{
   std::array<T, R * C> m_data;
};

int main() 
{
   matrix<float, 2, 2> a = { 1,2,3,4 }; // COMPILER ERROR!
}

Clang 报告没有匹配的构造函数!

我尝试编写以下形式的构造函数

matrix(std::array<T,R*C> a);

并尝试尝试 &&因为我认为所讨论的表达式的右侧是暂时的。这让我有些困惑。正如我们所期望的,它会被创建然后分配(!)到 a 的值。 。

最佳答案

就像评论中提到的其他人一样,您需要 std::initializer_list<T> matrix 的构造函数类。

#include <array>            // std::array
#include <initializer_list> // std::initializer_list
#include <algorithm>        // std::copy
#include <cassert>

template<typename T, std::size_t R, std::size_t C>
class matrix
{
   std::array<T, R * C> m_data;
public:
   matrix(const std::initializer_list<T> list)
  //            ^^^^^^^^^^^^^^^^^^^^^^^ --> constructor which takes std::initializer_list
   {
      assert(R * C == list.size());
      std::copy(list.begin(), list.end(), m_data.begin());
   }
};

int main()
{
   matrix<float, 2, 2> a = { 1,2,3,4 }; // now compiles
}

( See live online )


但是,这不是编译时的,并且会带来以下缺点:

  • 它不会检查传递的类型是否相同。
  • 无法在编译时检查传递列表的大小,如 std::initializer_list是/不能是编译时间。
  • 第三,它可以缩小转换范围。

为了禁止上述情况,一种解决方案是提供一个可变参数模板构造函数,它可以在编译时进行上述检查。

如下所示:( See live online )

#include <array>            // std::array
#include <initializer_list> // std::initializer_list
#include <type_traits>      // std::conjunction, std::is_same
#include <utility>          // std::forward     

// traits for checking the types (requires C++17)
template <typename T, typename ...Ts>
using are_same_types = std::conjunction<std::is_same<T, Ts>...>;

template<typename T, std::size_t R, std::size_t C>
class matrix
{
   std::array<T, R * C> m_data;
public:
   template<typename... Ts>
   constexpr matrix(Ts&&... elemets) noexcept
   {
      static_assert(are_same_types<Ts...>::value, "types are not same!");
      static_assert(sizeof...(Ts) == R*C, "size of the array does not match!");
      m_data = std::array<T, R * C>{std::forward<Ts>(elemets)...};
   }
};

int main()
{
   matrix<float, 2, 2> a{ 1.f,2.f,3.f,4.f }; // now compiles
   // matrix<float, 2, 2> a1{ 1,2,3,4 };              // error: narrowing conversion!
   // matrix<float, 2, 2> a1{ 1.f,2.f,3.f, 4 };       // error: types are not same!
   // matrix<float, 2, 2> a1{ 1.f,2.f,3.f,4.f, 5.f }; // error: size of the array does not match!
}

关于c++ - 我如何在我的矩阵类中获得此功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58638425/

相关文章:

c++ - 令人困惑的编译器错误

c++ - QPixmap 图像文件未出现在 QGraphicsScene 上

c++ - 无法将模板子类转换为不同的模板实例

python - 如何将属性严格保留为 pydantic 类的属性

c++ - 如何优化 C++ 类容器的加法运算符?

c++ - 通用模板函数总是返回整数值

c++ - 如何使我的 uninitialised_allocator 安全?

c++ - clang : warning: argument unused during compilation: '-stdlib=libc++'

c++ - 找到最小的未使用号码

带有 std::begin()、std::end() 问题的 C++11 自动迭代器类型