gpt4 book ai didi

c++ - 特征中的 typedef 与类中的 typedef

转载 作者:可可西里 更新时间:2023-11-01 16:37:21 26 4
gpt4 key购买 nike

出于教育目的,我正在查看 Eigen 源代码。我注意到对于每个具体类模板 X在层次结构中,有一个 internal::traits<X>定义。一个典型的例子可以在 Matrix.h 中找到:

namespace internal {
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
struct traits<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
{
typedef _Scalar Scalar;
typedef Dense StorageKind;
typedef DenseIndex Index;
typedef MatrixXpr XprKind;
enum {
RowsAtCompileTime = _Rows,
ColsAtCompileTime = _Cols,
MaxRowsAtCompileTime = _MaxRows,
MaxColsAtCompileTime = _MaxCols,
Flags = compute_matrix_flags<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::ret,
CoeffReadCost = NumTraits<Scalar>::ReadCost,
Options = _Options,
InnerStrideAtCompileTime = 1,
OuterStrideAtCompileTime = (Options&RowMajor) ? ColsAtCompileTime : RowsAtCompileTime
};
};
}

现在我理解 traits 是一种扩展现有类的方式,您不想使用与某些新代码相关的额外信息来修改这些类。例如,类模板的用户 Foo<class TAllocator>可能想利用现有的内存分配器 FastAllocAlignedAlloc , 但 Foo 需要知道如何与这两个接口(interface),因此 FooTraits<AlignedAlloc>::allocate()FooTraits<FastAlloc>::allocate()由用户定义,又由 Foo 使用.

但是,在这种情况下,我并不能轻易看出仅指定 Scalar 的问题。在每个派生类中,即有 Matrix定义 Matrix::Scalar在类主体中使用 typedef。使用 traits 类的优势是什么?是否只是为了保持代码整洁,即将每个类的所有相关属性存储在 traits 类中?

根据 Nicol Bolas 的回复进行编辑:我理解其中一些 typedef 可能需要保持“内部”,即不应该暴露给用户,这将解释特征类。这似乎是有道理的,但是其中一些类型定义,例如 Scalar , 通过 Matrix 基类中的 typedef 对外界可用:

template<typename Derived> class MatrixBase
: public DenseBase<Derived>
{
public:

typedef MatrixBase StorageBaseType;
typedef typename internal::traits<Derived>::StorageKind StorageKind;
typedef typename internal::traits<Derived>::Index Index;
typedef typename internal::traits<Derived>::Scalar Scalar;
typedef typename internal::packet_traits<Scalar>::type PacketScalar;
typedef typename NumTraits<Scalar>::Real RealScalar;

这让我们回到最初的问题:为什么不是 Scalar只是 Matrix 中的一个 typedef本身?除了文体选择之外还有什么原因吗?

最佳答案

我怀疑,因为特征类是 internal ,这就是使用特征类的意义所在。也就是说,将这些东西保留在内部。这样,Matrix没有很多奇怪的定义等,即使在其私有(private)接口(interface)中也是如此。

考虑示例中的枚举。那些“枚举”(又名:static constexpr C++11 之前的变量)看起来不像是用户应该知道的任何内容。这是一个实现细节,因此应该隐藏。


MatrixBase的问题是CRTP问题。

参见,Matrix会这样定义:

class Matrix : public MatrixBase<Matrix>

这个部分定义会导致两件事发生:

  1. 如果 Matrix还没有被声明为类类型,那么它就成为一个名称可以被引用和使用的合法类。

  2. 模板MatrixBase必须用 Matrix 类型实例化. 现在

这里的问题是“现在”,Matrix是一个不完整类。编译器尚未进入该定义的主体,因此编译器对其内部结构一无所知。但是MatrixBase必须立即实例化。

因此,MatrixBase不能使用 Derived 的任何内容它提供的类。如果Matrix里面有一些 typedef,MatrixBase<Derived> 无法看到它。

现在,MatrixBase<Derived> 的成员函数可以查看 Derived 中的定义,因为那些是在定义完整类之后定义的。即使这些函数是在类的范围内定义的。

但是你不能拥有 MatrixBase 的属性访问 Derived 的属性.因此,特征是间接的。特征类可以使用基于不完整类型的特化来将定义公开给 MatrixBase .

关于c++ - 特征中的 typedef 与类中的 typedef,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39132754/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com