我是 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()
。
如何使用
类型的参数声明构造函数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
宏。