Definition_________________________问题
!!You can skip here and directly go to■ Question Summary !!
我设计了一个灵活但内存高效的类,它适用于各种情况,其中只有选择特性:链接。
另外,我为每个特征提供了ID,当用户只请求类的特定特征时,就会使用它。
我编写了满足这些属性的自己的类,使用多继承 of 未命名枚举和可变模板。
见下文:
Triits.h
struct TriT
{
struct Centroid
{
Point3D centroid;
struct ID { enum : utin8_t { CENTROID = 1 }; }; // 0000 0001
};
struct Area
{
double area;
struct ID { enum : utin8_t { AREA = 2 }; }; // 0000 0010
};
struct Perimeter
{
double perimeter;
struct ID { enum : utin8_t { PERIMETER = 4 }; }; // 0000 0100
};
... // More traits...
};Triangle.h
#include "TriTraits.h"
enum class TRI_TRAIT_ID : uint8_t {}; // strong type
template<class... Traits>
struct TriangleT : Traits...
{
struct IDs : Traits::ID...
{
enum : uint8_t {
NONE = 0, // 0000 0000
ALL = 255 // 1111 1111
};
};
void ComputeTrait(TRI_TRAIT_ID _requestedIDs)
{
... // Implementation will be written somehow, using bitwise & operator.
}
};例如,如果定义自己的三角形类型MyTri<TriT::Area, TriT::Perimeter> myTri,编译器所看到的可能如下所示:
struct MyTri
{
double area;
double perimeter;
struct IDs // Since enum can't be inherited, it has 3 individual unnamed enums in it
{
enum : uint8_t { AREA = 2 };
enum : uint8_t { PERIMETER = 4 };
enum : uint8_t {
NONE = 0,
ALL = 255
};
};
} myTri;这个自定义三角形类型将通过使用按位的调用ComputeTraits(...)来计算的一些特征,如下所示:
myTri.ComputeTraits(MyTri::IDs::AREA | MyTri::IDs::PERIMETER); // Compute area and perimeter问题出现在这里,:假设有Rectangle.h和Pentagon.h**,...** NthPolygon.h,以同样的方式出现。
我希望我的每个自定义多边形类型为其ComputeTrait(...)获取一个ComputeTrait(...)参数(因此我为它使用了枚举类),以防止采用混合类型的多边形特征的愚蠢操作,例如
myTri.ComputeTraits(MyTri::IDs::AREA | MyRect::IDs::PERIMETER); // Mixed traits of a triangle and of a rectangle.因此,我想重载|operator,它在NthPolygon::IDs::...的每个作用域中只接受未命名的枚举。
我尝试将重载的模板操作符写入( NthPolygon::IDs::...的private作用域),但这失败了,因为类内操作符重载总是将第一个参数作为自身:链接。
使其成为全局范围的friend也失败了,因为每个N个多边形类都会有超过一个重载的|operator。
enum class N_TH_POLYGON_TRAIT_ID : uint8_t {}; // strong type
struct NthPolygon
{
...
struct IDs
{
...
private:
template<typename TRAIT_ID1, typename TRAIT_ID2>
N_TH_POLYGON_TRAIT_ID operator|(TRAIT_ID1 _id1, TRAIT_ID2 _id2) // Error : too many operators for this operator function
{ return static_cast<N_TH_POLYGON_TRAIT_ID>(static_cast<utin8_t>(_id1) | static_cast<utin8_t>(_id2)); }
template<typename TRAIT_ID1, typename TRAIT_ID2>
friend N_TH_POLYGON_TRAIT_ID operator|(TRAIT_ID1 _id1, TRAIT_ID2 _id2) // Error : more than 1 operator "|" matches these operands
{ return static_cast<N_TH_POLYGON_TRAIT_ID>(static_cast<utin8_t>(_id1) | static_cast<utin8_t>(_id2)); }
};
} myTri;Summary_________________________问题
在下面的情况下,如何使模板重载的operator|只从特定类获取参数(未命名枚举)?
enum class STRONG_TYPE_TRI_TRAIT_ID : uint8_t {};
struct Triangle
{
struct IDs {
enum : utin8_t { A = 1 };
enum : utin8_t { B = 2 };
enum : utin8_t { C = 3 };
};
};
template<typename TRI_TRAIT_ID1, typename TRI_TRAIT_ID2>
STRONG_TYPE_TRI_TRAIT_ID operator|(TRI_TRAIT_ID1 _id1, TRI_TRAIT_ID2 _id2)
{ return static_cast<STRONG_TYPE_TRI_TRAIT_ID>(static_cast<uint8_t>(_id1) | static_cast<uint8_t>(_id2)); }enum class STRONG_TYPE_RECT_TRAIT_ID : uint8_t {};
struct Rectangle
{
struct IDs {
enum : utin8_t { A = 1 };
enum : utin8_t { B = 2 };
enum : utin8_t { C = 3 };
};
};
template<typename RECT_TRAIT_ID1, typename RECT_TRAIT_ID2>
STRONG_TYPE_RECT_TRAIT_ID operator|(RECT_TRAIT_ID1 _id1, RECT_TRAIT_ID2 _id2)
{ return static_cast<STRONG_TYPE_RECT_TRAIT_ID >(static_cast<uint8_t>(_id1) | static_cast<uint8_t>(_id2)); }int main(void)
{
Triangle::IDs::A | Triangle::IDs::B; // OK
Triangle::IDs::A | Rectangle::IDs::B; // Error
...
return 0;
}发布于 2020-03-28 11:24:49
不确定它是否满足了您的要求,但您可能会这样做:
template <typename Tag>
struct TriT
{
enum class ID_t : uint8_t {};
friend ID_t operator | (ID_t lhs, ID_t rhs)
{
return ID_t(uint8_t(lhs) | uint8_t(rhs));
}
struct Centroid
{
Point3D centroid;
struct ID { static const ID_t CENTROID = ID_t(1); }; // 0000 0001
};
struct Area
{
double area;
struct ID { static const ID_t AREA = ID_t(2); }; // 0000 0010
};
struct Perimeter
{
double perimeter;
struct ID { static const ID_t PERIMETER = ID_t(4); }; // 0000 0100
};
};
template<typename TRI_TRAIT_ID, class... Traits>
struct TriangleT : Traits...
{
struct IDs : Traits::ID...
{
static constexpr TRI_TRAIT_ID NONE = TRI_TRAIT_ID(0);
static constexpr TRI_TRAIT_ID ALL = TRI_TRAIT_ID(255);
};
void ComputeTrait(TRI_TRAIT_ID _requestedIDs)
{
// Implementation will be written somehow, using bitwise & operator.
}
};与用法:
struct TriTag;
struct RectTag;
using MyTri = TriangleT<TriT<TriTag>::ID_t, TriT<TriTag>::Area, TriT<TriTag>::Perimeter>;
using MyRect = RectT<TriT<RectTag>::ID_t, TriT<RectTag>::Area, TriT<RectTag>::Perimeter>;
int main()
{
MyTri myTri;
myTri.ComputeTrait(MyTri::IDs::AREA | MyTri::IDs::PERIMETER);
//myTri.ComputeTrait(MyTri::IDs::AREA | MyRect::IDs::PERIMETER); // error as expected
}https://stackoverflow.com/questions/60899980
复制相似问题