恰当的模板习语(直觉)
Proper template idiom (intuition)
我正在尝试从更深入的概念中理解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>::identity
和Matrix::identity<T>
之间没有什么不同。它只是看起来像CCD_ 9。所以没有任何成语。
但另一方面,许多实际问题会让你选择更好的。
-
什么是
Matrix
0?如果Matrix<T>
表示元素类型为T
的矩阵类,那么Matrix
本身是什么?它是一个类模板,因此在没有实例化的情况下不能有任何成员。在这种情况下,您应该定义一个单独的类(例如,名为MatrixUtility
(,并使用MatrixUtility::identity<T>
。听起来很吵,对吧? -
但是,
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
实际上是必要的。
- 尽管如此,您也需要
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
;而不是遵循固定的习语。
- 概念可以与 CRTP 习语一起使用吗?
- 复制和交换习语和迭代器
- 为什么当我做复制和交换习语时不调用我的复制构造函数?
- 漂亮的计数器习语的错误或格式错误的静态订单惨败?
- C++17 pimpl 习语上下文中的自定义迭代器
- 在 MyVector 中实现写入时复制习语
- 视觉 "extern __forceinline "是什么 c++ 习语?
- C 习语使用C库时,该C库期望功能指针
- 为什么 std::swap 不使用 swap 习语?
- 如何使用擦除删除习语从结构向量中删除值
- C++中的Singleton习语
- 在 C++11 中实现复制和交换习语的更好方法
- N 个并发读取器和 1 个生产者的习语或模式
- pImpl习语-将私有类实现放在cpp中有什么缺点
- 不能使用 pimpl 习语将用户定义的向量插入到封装的向量中
- Python -> C++ 习语:将 lambda 表达式存储在映射/容器中
- 安全方便的通用散列(用于 STL 无序集和映射)习语?
- 指向可配置实现的Pimpl习语
- 与构造函数参数相关的异常安全的习语
- 用C++处理身体习语