c++ - 正确的模板习语(直觉)
问题描述
我试图以更深层次的概念理解 C++ 模板元编程。我不明白的是模板的真正含义。具体来说,具有静态成员的模板类的习语是什么。举个例子:
template <class T>
class Matrix {
private:
public:
static constexpr Matrix<T> Identity(int,int);
static constexpr Matrix<T> Zero(int,int);
static constexpr Matrix<T> Null = Matrix();
typdef value_type;
Matrix();
Matrix(int,int);
}
Matrix
显然构造典型矩阵的静态成员函数。我的想法是思考文本(习语)的Matrix<T>::Identity
方式将是一个类的单位矩阵 value_type = T
。
TL;博士
重申一下,我相信上面的模板会生成一组Matrix<T>::Identity
具有各自“类型”静态成员的类。这是与一些其他直观语义的比较,Matrix::Identity<T>()
后者将是T
所有矩阵的类型标识。哪个是对的?
解决方案
Matrix<T>::identity
没有任何其他条件,和之间没有什么不同Matrix::identity<T>
。它看起来像someFunction<T>
。所以没有任何成语。
但另一方面,很多实际问题会让你选择更好的。
是什么
Matrix::identity<T>
?ifMatrix<T>
表示一个矩阵类,其元素的类型为T
,它Matrix
本身是什么?它是一个类模板,所以没有实例化就不能有任何成员。在这种情况下,您应该定义一个单独的类(例如,命名MatrixUtility
),并使用MatrixUtility::identity<T>
. 听起来很吵,对吧?但是,
Matrix::identity
(或MatrixUtility::identity
)呢?通常T
可以在上下文中推断出类型。例如:
Matrix<int> a = MatrixUtility::identity(3, 3); // T=int is required in this context.
auto lambda = [](Matrix<double>){};
lambda(MatrixUtility::identity(2, 2)); // T=double is required in this context.
所以有一个棘手的方法来实现它,通过自动扣除operator T()
:
struct Helper{
template<typename T>
operator Matrix<T>(){
// construct and return
};
int w, h;
};
struct MatrixUtility{
Helper identity(int w, int h){
return Helper{ w, h };
}
};
在这种情况下,MatrixUtility
实际上是必要的。
- 尽管如此,您也需要
MatrixUtility::identity<T>
,因为有时需要单态:
template<typename T>
void foo(Matrix<T>);
auto a = MatrixUtility::identity(3, 3); // unexpected, a has type of Helper.
auto b = MatrixUtility::identity<int>(3, 3); // ok.
foo(MatrixUtility::identity(3, 3)); // ill-formed, T is not deducible.
foo(MatrixUtility::identity<int>(3, 3)); // well-formed.
最后,您选择的实现应该取决于您真正需要的。你需要一个多态性,然后选择MatrixUtility::identity
;您需要最简化,然后选择Matrix<T>::identity
;而不是遵守固定的成语。
推荐阅读
- c++ - 访问和修改函数内部的结构数组
- kubernetes - Kubernetes Liveness 探针和环境变量
- react-native - 本地图像现在显示 React Native
- python - 计算新的分箱值列时出错
- .net - 使用现有 WSDL 文件在 .net core 3.1 下创建 Soap 服务
- node.js - 将 SSL 证书添加到 Angular 应用程序后,后端带有 expressJS 的 Angular 项目不起作用
- python - 将一个零从列表移到末尾,并将非零保留原样
- excel - 在excel中复制,重命名和验证多个文件和路径的成功
- netsuite - Netsuite 客户端脚本在某些项目添加到销售订单时创建弹出窗口
- javascript - 从 React 仓库安装和使用 React