C++ 在mixin类型之间复制数据
我希望能够将一些不同类型的数据添加到对象中(这里称为“A”和“B”)。如果我为两个不同的对象以相同的顺序添加它们,那么将一个对象复制到另一个对象就可以了(例如,C++ 在mixin类型之间复制数据,c++,mixins,C++,Mixins,我希望能够将一些不同类型的数据添加到对象中(这里称为“A”和“B”)。如果我为两个不同的对象以相同的顺序添加它们,那么将一个对象复制到另一个对象就可以了(例如,A abPoint1;A abPoint2=abPoint1;)。但是,如果我以不同的顺序添加它们(例如,A abPoint;B baPoint=abPoint;//编译器错误),因为类型签名不同。有没有办法在不显式处理指数数量的mixin组合的情况下做到这一点 以下是用于测试的MWE: // Standard point represe
A abPoint1;A abPoint2=abPoint1;
)。但是,如果我以不同的顺序添加它们(例如,A abPoint;B baPoint=abPoint;//编译器错误
),因为类型签名不同。有没有办法在不显式处理指数数量的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;
}
//标准点表示法
结构点
{
双x,y,z;
};
//向点添加“A”值的混合
模板
A类:公共基地
{
公众:
双a;
};
//向点添加“B”值的混合
模板
B类:公共基地
{
公众:
双b;
};
int main()
{
一个点;
B点;
//A a2Point=b点;//显然我们不能这样做
A点;
B点;
abPoint=baPoint;//像这样的事情似乎应该是可能的
返回0;
}
更好的是,是否有一种方法可以只复制“可用”的数据片段?即:
A<B<C<D<Point>>>> abcdPoint;
A<C<Point>> acPoint;
abcdPoint = acPoint;
abcdPoint;
A点;
abcdPoint=acPoint;
我只会复制A和C中的成员。为了能够显示我认为答案是什么,而不需要真正测试它是否有效,我将称之为答案
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> > {};
模板
甲级{
公众:
A运算符=(常数&右侧){
//不会阻止所有错误,但会捕获一些错误:
静态断言(std::is_base_of::值,“CRTP故障”);
自动*dis=静态_转换(此);
BASE::operator=(右);
dis->a=右侧。a;
归还这个;
}
双a;
};
模板
B类{
公众:
B运算符=(常量和B右侧){
//不会阻止所有错误,但会捕获一些错误:
静态断言(std::is_base_of::值,“CRTP故障”);
自动*dis=静态_转换(此);
dis->b=右侧。b;
BASE::operator=(右);
归还这个;
}
双b;
};
类点:公共A点{};
类B点:公共B点{};
类abPoint:public B{};
类B点:公共A{};
我尽我所能充实了你的例子。将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;
}
#包括
结构点
{
公众:
双x,y,z;
};
//向点添加“A”值的混合
模板
A类:公共基地
{
公众:
A运算符=(常量点和rhs)
{
点::运算符=(rhs);
归还*这个;
}
模板
A和运算符=(常数T_RHS和RHS)
{
基::运算符=(rhs);
a=rhs.a;
归还*这个;
}
双a;
};
//向点添加“B”值的混合
模板
B类:公共基地
{
公众:
B和运算符=(常数点和rhs)
{
点::运算符=(rhs);
归还*这个;
}
模板
B和运算符=(常数T_RHS和RHS)
{
基::运算符=(rhs);
b=rhs.b;
归还*这个;
}
双b;
};
int main()
{
点-点;
一个点;
aPoint=点;
B点;
B点=点;
BB点;
AabPoint;
abPoint=baPoint;
//失败
//aPoint=b点;
//b点=a点;
//这很有效
aPoint.Point::operator=(bPoint);
点::运算符=(aPoint);
返回0;
}
。参考CRTP的这个问题的答案可能会对您有所帮助。它将允许您重铸“this”和其他参数,以测试它们是否具有所需的数据,并编写一个运算符=来执行该操作。嗯,我不确定我是否遵循了这一点。所以这里我需要模板点?那么我应该为哪个类编写运算符=?每个人都会复制他们自己的数据吗(他们会自动称为“递归的”?)?嗯。。假设你有一个C类:带有成员变量double a的公共基;然后你做到了——一点;C点;cPoint=aPoint@KorreyD不太一样——它实际上比这个更强。如果我有一个acPoint和一个aPoint,我希望acPoint=aPoint复制A类中的所有内容,因为这是它们唯一的共同点。同样,acPoint=point只会复制point的成员。但它需要扩展,就像一个abcdPoint;A点;abcdPoint=acPoint只从A和C复制成员。明白我的意思吗?我在问题中添加了这个描述,因为这才是我真正想要的。在我尝试一个更复杂的例子之前,这不应该起作用吗?我得到了“从点到非标量类型A的转换请求”-这不是模板赋值运算符应该处理的吗?您需要在运算符=。因为除非a(或b)在右边存在,否则它不会编译,所以它可能会工作。在这个要点中,我有意不复制operator=中的“a”,这样它只会从点复制数据。但似乎没有使用模板运算符,而是使用默认运算符=?此代码->A aPoint=点;调用复制构造函数(因为aPoint同时被声明和赋值)。您在代码中覆盖的是复制赋值运算符。所以如果你想让它击中你想做的那段代码:一个aPoint;aPoint=点@KorreyD啊,当然,谢谢。回到更难的情况。。。哈维德,知道为什么普通赋值运算符失败了吗?这就解决了排序问题(AB vs BA),但如果存在不同的混合子集(例如AC vs AB),它看起来就不起作用了-也就是说,AC将尝试从传入的任何东西(AB)复制C,而这将失败,对吗?rhs的类型是错误的。我的猜测是,如果将rhs投射到某个点,正常=将起作用。