【问题标题】:Copying data between mixin types在 mixin 类型之间复制数据
【发布时间】:2015-12-09 20:58:47
【问题描述】:

我有一些不同类型的数据希望能够添加到对象(这里称为“A”和“B”)。如果我为两个不同的对象以相同的顺序添加它们,将一个复制到另一个可以正常工作(例如A<B<Point> > abPoint1; A<B<Point> > abPoint2 = abPoint1;)。但是,如果我以不同的顺序添加它们(例如A<B<Point> > abPoint; B<A<Point> > baPoint = abPoint; // compiler error),因为类型签名不一样。有没有办法在不明确处理指数数量的 mixin 组合的情况下做到这一点?

这是一个用于测试的 MWE:

// Standard point representation
struct Point
{
    double x,y,z;
};

// A mixin to add an 'A' value to a point
template<class Base>
class A : public Base
{
public:

    double a;
};

// A mixin to add an 'B' value to a point
template<class Base>
class B : public Base
{
public:

    double b;
};

int main()
{
  A<Point> aPoint;

  B<Point> bPoint;

  // A<Point> a2Point = bPoint; // obviously we can't do this

  A<B<Point> > abPoint;
  B<A<Point> > baPoint;

  abPoint = baPoint; // Something like this seems like it should be possible

  return 0;
}

更好的是,有没有办法只复制“可用”的数据片段?那就是:

A<B<C<D<Point>>>> abcdPoint; 
A<C<Point>> acPoint; 
abcdPoint = acPoint;

只会复制 A 和 C 的成员。

【问题讨论】:

  • stackoverflow.com/questions/33789582/…。引用CRTP的这个问题的答案可能会对您有所帮助。它将允许您重铸 'this' 和其他参数以测试它们是否具有您需要的数据,并编写一个 operator = 来执行操作。
  • 嗯,我不确定我是否遵循这一点。所以在这里我需要模板点?那么我会为哪个类写一个operator=?每个人都只是复制自己的数据吗(它们会自动称为“递归”吗?)?
  • hmm.. 假设你有一个类 C : public Base 有一个成员变量 double a;然后你做了- A aPoint; C cPoint; cPoint = aPoint
  • @KorreyD 不完全——它实际上比这更强大。如果我有一个 A> acPoint 和一个 A aPoint,我希望 acPoint = aPoint 复制 A 类中的所有内容,因为这是它们唯一的共同点。同样,acPoint = point 只会复制 Point 的成员。但它需要扩展,比如 A>>> abcdPoint; A> acPoint; abcdPoint = acPoint 只会复制 A 和 C 的成员。明白我的意思吗?我已将此描述添加到问题中,因为这确实是我想要的。

标签: c++ mixins


【解决方案1】:

为了能够展示我认为的答案,而无需真正测试它是否有效,我将其称为答案。

template<class BASE>
class A {
public:
  A<BASE> operator=(const &A<BASE> right) {
    // does not block all errors, but catches some:
    static_assert( std::is_base_of< A, BASE >::value, "CRTP failure" );
    auto* dis = static_cast<BASE*>(this);
    BASE::operator=(right);
    dis->a = right.a;
    return this;
  }
  double a;
};

template<class BASE>
class B {
public:
  B<BASE> operator=(const &B<BASE> right) {
    // does not block all errors, but catches some:
    static_assert( std::is_base_of< B, BASE >::value, "CRTP failure" );
    auto* dis = static_cast<BASE*>(this);
    dis->b = right.b;
    BASE::operator=(right);
    return this;
  }
  double b;
};


class aPoint: public A<aPoint>, Point {};

class bPoint: public B<bPoint>, Point {};

class abPoint: public B < A<abPoint> > {};

class baPoint: public A < B<baPoint> > {};

【讨论】:

  • 在我尝试一个更复杂的例子之前,这不应该工作吗? gist.github.com/daviddoria/4ea5d826684993b1e4ef 我收到“请求从 Point 转换为非标量类型 A” - 这不是模板赋值运算符应该处理的内容吗?
  • 您需要在 operator= 中复制 a 或 b。由于除非右侧存在 a(或 b),否则它不会编译,因此它可能会工作。
  • 在那个要点中,我故意不在 operator= 中复制“a”,以便它只会从 Point 复制数据。但似乎模板 operator= 没有被使用,而是默认的 operator=?
  • 这段代码 -> A aPoint = point;调用复制构造函数(因为同时声明和分配了 aPoint)。您在代码中覆盖的内容是复制赋值运算符。所以如果你想让它命中你想做的那段代码: A aPoint; aPoint=点;
  • @KorreyD 啊,当然,谢谢。回到更难的情况......哈哈
【解决方案2】:

我尽我所能充实了你的例子。将 abPoint 复制到 baPoint 中有效。

#include <iostream>

struct Point
{
public:
    double x,y,z;
};

// A mixin to add an 'A' value to a point
template<class Base>
class A : public Base
{
public:
    A& operator=( const Point& rhs )
    {
        Point::operator=(rhs);
        return *this;
    }

    template <typename T_RHS>
    A& operator=( const T_RHS& rhs )
    {
        Base::operator=(rhs);
        a = rhs.a;
        return *this;
    }

    double a;
};

// A mixin to add an 'B' value to a point
template<class Base>
class B : public Base
{
public:
    B& operator=( const Point& rhs )
    {
        Point::operator=(rhs);
        return *this;
    }

    template <typename T_RHS>
    B& operator=( const T_RHS& rhs )
    {
        Base::operator=(rhs);
        b = rhs.b;
        return *this;
    }

    double b;
};

int main()
{
  Point point;

  A<Point> aPoint;
  aPoint = point;

  B<Point> bPoint;
  bPoint = point;

  B< A<Point> > baPoint;
  A< B<Point> > abPoint;
  abPoint = baPoint;

  // Fails
  //aPoint = bPoint;
  //bPoint = aPoint;

  // This works
  aPoint.Point::operator=(bPoint);
  bPoint.Point::operator=(aPoint);

  return 0;
}

【讨论】:

  • 奇怪,知道为什么正常的赋值运算符会失败吗?所以这解决了排序问题(AB vs BA),但是如果有不同的mixin子集(例如AC vs AB),它看起来将不起作用 - 那就是AC将尝试从传入的任何内容中复制C( AB)哪个会失败,对吧?
  • rhs 的类型错误。我的猜测是,如果 rhs 被投射到一个点,正常的 = 会起作用。
猜你喜欢
  • 2015-12-08
  • 1970-01-01
  • 2019-03-14
  • 1970-01-01
  • 1970-01-01
  • 2022-08-03
  • 2019-02-11
  • 1970-01-01
相关资源
最近更新 更多