恰当的模板习语(直觉)

Proper template idiom (intuition)

本文关键字:直觉 习语      更新时间:2024-03-29

我正在尝试从更深入的概念中理解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);
}

CCD_ 1的静态成员函数显然构造了典型的矩阵。我的想法是,思考文本(成语(Matrix<T>::Identity的方式将是具有value_type = T的类的恒等矩阵。

TL;DR

重申一下,我相信上面的模板生成了一个类集,这些类具有各自"类型"的静态成员Matrix<T>::Identity。这与某些Matrix::Identity<T>()的其他直观语义相比较,后者对于所有矩阵而言将是类型为T的恒等式。哪个是正确的?

在没有任何其他条件的情况下,Matrix<T>::identityMatrix::identity<T>之间没有什么不同。它只是看起来像CCD_ 9。所以没有任何成语。

但另一方面,许多实际问题会让你选择更好的。

  1. 什么是Matrix0?如果Matrix<T>表示元素类型为T的矩阵类,那么Matrix本身是什么?它是一个类模板,因此在没有实例化的情况下不能有任何成员。在这种情况下,您应该定义一个单独的类(例如,名为MatrixUtility(,并使用MatrixUtility::identity<T>。听起来很吵,对吧?

  2. 但是,Matrix::identity(或MatrixUtility::identity(呢?通常可以在上下文中推导出类型CCD_ 18。例如:

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实际上是必要的。

  1. 尽管如此,您也需要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;而不是遵循固定的习语。