如何使用 T 类型的 nRow*nCol 参数来声明构造函数?

问题描述 投票:0回答:1

我是 C++ 新手,刚刚学会了如何使用模板。 我想编写一个具有以下模板参数的 Matrix 类:

template < int nRow ,int nCol ,typename T = double >
class ZDMatrix  {
public:
    ZDMatrix();
    ZDMatrix( T arg0 );
    ZDMatrix( T arg0 ,T arg1 );
    // ... How to declare the constructor with exactly nRow*nCol arguments of type T ??
    // ZDMatrix( T arg0 ,T arg1 ,... ) {
    //     ... number or argN should be nRow*nCol
    // }
};

我希望能够像这样使用矩阵:

ZDMatrix<2,3>   matX( 1 ,1.1 ,1.2 ,2,2.1,2.2 );  // auto convert int 1 to double 1.0

作为替代方案,我已经尝试使用

std::initializer_list

ZDMatrix<nRow,nCol,double>::ZDMatrix( std::initializer_list<T> list )  {
    assert( list.size() == nRow*nCol );
    // ...
}

但是参数数量的检查是在运行时而不是

static_assert()

c++ templates c++20 variadic-templates class-template
1个回答
1
投票

如何使用

nRow*nCol
类型的参数声明构造函数
T
??

一种方法是使用

sizeof...
,可以检查参数包中的元素数量,假设您使用带有可变模板参数的构造函数。应用 SFINAE,它看起来像:

#include <type_traits> // std::conjunction (since c++17), std::enable_if, std::is_same

template <std::size_t nRow, std::size_t nCol, typename T = double>
class ZDMatrix
{
   std::array<T, nRow* nCol> mData{};

public:
   template <typename... Ts, 
      std::enable_if_t<sizeof...(Ts) == nRow * nCol &&  // No. of args must be equal tonRow * nCol
      std::conjunction_v<std::is_same<T, Ts>...> // or std::is_convertible
      >* = nullptr>
      ZDMatrix(Ts&&... args)
      : mData{ std::forward<Ts>(args)... }
   {}
};

观看现场演示


或者,您可以在构造函数体内设置

static_assert
上述两个 SFINAE 条件。或者在 C++20 中,您可以对相同条件执行
requires
约束
,如下所示:

template <std::size_t nRow, std::size_t nCol, typename T = double>
class ZDMatrix
{
   std::array<T, nRow* nCol> mData{};

public:
   template <typename... Ts>
      requires (sizeof...(Ts) == nRow * nCol) && (std::same_as<T, Ts> && ...)
   ZDMatrix(Ts&&... args)
      : mData{ std::forward<Ts>(args)... }
   {}
};

观看现场演示


顺便说一下,在使用模板化构造函数时,编译器总是会提示类型不匹配。我会选择模板解决方案,除非有特殊要求需要

std::initializer_list<T>
assert
宏。

© www.soinside.com 2019 - 2024. All rights reserved.