Variadic模板参数包只接受无符号int或size_t作为其类型



我正在尝试使用一组带有可变参数的模板类。我面前有几个选项可以选择。在我的任何模板被声明或定义之前,我目前有这些原型:我熟悉模板,但在使用模板时,我对可变类型没有太多经验,所以语法有时会让我有点困惑。因为它们都是空壳,所以它们目前正在编译。

template<typename ClassType, typename... Args>  class MatrixReference;
template<typename ClassType, typename... Args>  class MatrixStorage;
template<typename ClassType, typename... Args>  class MatrixAllocation;

我有一个用户端类,它将根据使用意图使用这些类;它目前是一个空壳,直到我用适当的行为正确定义了其他类:

template<typename ClassType, typename... Args>
class Matrix {      
};

上面显示的原型中的类的其余部分将从基类继承,这样上面的用户类将有一个容器,这样容器将是:std::vector<std::unique_ptr<MatrixBase>>std::vector<shared_ptr<MatrixBase>>,并且向量将只包含列出的原型中每种类型的1个。例如,向量[0]将包含MatrixStorage,向量[1]将容纳MatrixReference,向量[2]将包含MatixAllocation。正如它们的名字所暗示的那样,每个类都有不同的职责。存储类将包含元素的原始堆栈副本。引用类将用于引用这些副本。当在堆上声明元素时,将使用分配类。基类如下:

template <typename ClassType = void>
class MatrixBase {
protected:
MatrixBase(){}
virtual ~MatrixBase(){}
}; // Matrix

我还考虑过从非模板库继承它们,因为这个类除了能够将不同的类类型存储到一个容器中之外什么都不做。我可能会继续将其更改为非模板类型,但目前我正在按原样使用它,以保持其派生类型的约定。

现在来看我的类模板的声明:我真的只需要在这里使用其中一个,因为所有模板都遵循相同的模式,但我无论如何都会显示所有3个,因为它们目前都是空壳。

// Stores All Of The Contents Of The Matrix
template<typename ClassType, typename... Args>
class MatrixStorage : public MatrixBase<ClassType> {
}; // MatrixStorage    
// Used To Reference The Storage Class Of The Matrix
template<typename ClassType, typename... Args>
class MatrixReference : public MatrixBase<ClassType> {
}; // MatrixReference
// Used Only When User Wants To Create A Matrix On The Heap
template<typename ClassType, typename... Args>
class MatrixAllocation : public MatrixBase<ClassType> {
}; // MatrixAllocation

我正在寻找的设计方法是,当使用这个类时,它遵循的模式是,第一种类型始终是矩阵将存储的数据类型,要么是int、float,要么是其他用户定义的类型;下一个参数是使用变参数的地方,这样,如果有人将模板实例化为这样:

Matrix<float,2,2> mat2x2; // Default constructor making it empty

这将生成一个2x2大小的浮动矩阵

Matrix<int,3,3,3> mat3x3x3; 

这将生成int 的3x3x3体积矩阵

因此变差模板部分将始终是+整数,并且最小要求将是Matrix<type, 1>,其中在某种意义上这将是标量或单元素矩阵或1x1矩阵。

这就是我可以选择的地方。我可以使用以下

  • size_t。。。N
  • 未签名。。。D
  • 类型名称。。。Args

目前,正如您所看到的,它是用最后一个选项声明的。所以现在主要的问题来了:

如果我决定使用参数包,其中我有一个助手类,如:

template <typename ClassType,typename... Dimensions>
class DimensionPack {
public: 
typename std::tuple<ClassType, std::tuple<Dimensions...> >::type Dim;
const unsigned int numarguments = sizeof...(Dimensions);
};

问题变成了;有没有一种已知的方法可以使同一类型的变分参数size_tunsigned int?如果是这样的话,可以举出一个例子,或者参考链接也会有所帮助;我已经搜索过了,但没有找到任何类似的有用的东西来帮助我度过难关。

如果没有,我不介意必须使用size_tunsigned int,但我更喜欢使用助手模板来为我打包和解压缩可变参数,这样我就不必在每个类中实现它。

我还有另外两个派生类,这里没有显示,但其中一个用于将它们记录到屏幕上,另一个用于从文件中读取和解析以及写入文件。

另请注意:对于超大数据集或超大矩阵:我还有一个助手类可以用于它们:

template<typename ClassType, std::size_t bufferSize>
class MatrixBuffer {
static std::vector<ClassType> matrixBuffer = std::vector<ClassType>().reserve( bufferSize );
};

编辑

我忘了把这个添加到原来的问题中,但为了更清楚一点,我现在添加它。我确实需要测试每个变参数的值,看看它是奇数还是偶数,它们的结果将被存储到一个向量中,该向量的大小与存储0表示偶数或1表示奇数的参数数量相当。这就是我倾向于使用参数包的原因之一,因为我可以将其传递给一个辅助函数,该函数将返回所需的向量。

std::size_t... Argstypename... Args不相同。第一个会期望像这样的整数

Matrix<float,2,2> mat2x2;

而第二个则期望使用类型
当然,您可以使用std::integral_content,但这会更详细:

template <std::size_t N>
using size = std::integral_constant<std::size_t, N>;
Matrix<float,size<2>,size<2>> mat2x2;

另一方面,您可以使用std::index_sequence:

template<typename ClassType, std::size_t... Dims>
class Matrix {
using Dimensions = std::index_sequence<Dims...>;
};

使用static_assert可以在编译时进行检查:

template <typename ClassType,typename... Dimensions>
class DimensionPack {
public:
DimensionPack(const Dimensions&... args){
checkType<Dimensions...>(args...);
}
~DimensionPack(){}
private:
template<typename T> void checkType(const T& t) {
static_assert(std::integral_constant<bool, std::is_same<T, size_t>::value>(), "T is not of type size_t");
}
template<typename T, typename... V> void checkType(const T& t, const V&... v) {
static_assert(std::integral_constant<bool, std::is_same<T, size_t>::value>(), "T is not of type size_t");
checkType<V...>(v...);
}
};

相关内容

最新更新