C++ 继承模式 + CRTP

标签 c++ inheritance

我正在尝试理解 ublas 中使用的模式。 模式是这样的:

struct vector : vector_expression<vector>

vector_expression 是这样的:

template<class E>
class vector_expression {
...
// no constructor or E pointer/reference in class
//
const E &operator () () const {
      return *static_cast<const E*>(this);
}

完整的源代码在这里: http://www.tena-sda.org/doc/5.2.2/boost/dd/d44/vector__expression_8hpp-source.html#l00088

我的问题是,*static_cast<const E*>(this) 是怎么做到的?工作?它依赖于继承吗?

下一个问题: 如果我得出

template<class E>
class vector_expression2 : private vector_expression<E>
{
    //friend class ublas::vector_expression<E>; // this is the fix
    typedef vector_expression<E> base;
    const E& operator()() const { return base::operator()(); } 
 };

我收到有关无法访问的编译器错误 vector_expression静态类型转换基地。为什么会这样?

谢谢

最佳答案

这是一个限制函数模板的技巧——限制类型的类别。有很多概念,例如 vector 表达式、标量表达式、矩阵表达式等。如果您想编写一个将 vector 与标量相乘的函数模板,您可以尝试编写

template<typename V, typename S>
some_type operator*(V v, S s);  // vector * scalar

template<typename V, typename S>
some_type operator*(S s, V v); // scalar * vector

但这行不通,因为两个声明本质上是等价的,而且没有人说 V 应该是 vector 表达式而 S 应该是标量表达式。因此,uBlas 开发人员所做的是使用 CRTP 来约束这些模板:

template<typename V, typename S>
some_Type operator*(vector_expression<V> ve, scalar_expression<S> se);

要使这项工作有效,所有标量表达式 S 都必须派生自 scalar_expression<S>并且所有 vector 表达式 V 都必须来自 vector_expression<V> .这样,仅当第一个操作数确实是 vector 的表达式并且第二个参数确实是标量的表达式时,才会考虑此运算符。您可以使用交换两个参数的第二个函数模板重载此函数模板,一切正常。

现在,为了能够从 V 和 S(派生类型)访问任何内容,我们需要从基类到派生类的强制转换。这就是基类中的转换运算符的用途。由于基类知道派生类(它是模板参数),所以这不是问题。选择允许此转换避免错误的最弱转换运算符是有意义的。这是 static_cast .它可用于将 base* 转换为 derived* 而无需任何显着开销。

我不明白你想用你的代码做什么

template<class E>
class vector_expression2 : private vector_expression<E>;

如果你想编写自己的 vector 表达式作为模板,你可以这样做:

template<class E>
class my_parameterized_vector_expression
: public vector_expression<my_parameterized_vector_expression<E> >;

我认为它不适用于私有(private)继承。如果您在此处使用私有(private)继承,至少所有采用 vector 表达式作为参数的函数模板将无法从基类访问转换运算符。

关于C++ 继承模式 + CRTP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3287102/

相关文章:

c++ - 如何在 C 和 C++ 中定义结构之间的某种继承?

c++ - Visual C++ vector 删除会增加内存使用量吗?

c# - 更改基类属性 setter 行为

c# - 使用 dllimport 为多个参数设置不同的字符集

c++ - C++中的访问冲突错误

ruby-on-rails - 继承的 Active Record 类的 link_to 问题

inheritance - 是否可以通过扩展组件来查看特定于功能的变量?

scala - 在 Scala 的父特性中声明子特性的 self 类型

c++ - 在glm中重用矩阵?

c++ - CvStereoCalibrate() 声明中 "InputOutputArray"的含义