■ 问题定义_________________________
<代码>!!您可以跳过这里,直接进入
■问题总结!!
我设计了一个灵活但记忆效率高的类,它适合各种情况,其中只有选择性特征:链接
另外,我为每个特性提供了ID,当用户只想请求类的特定特性时,可以使用该ID。
我编写了自己的类来满足这些属性,使用可变参数模板的未命名枚举的多个继承。
见下文:
▼TriTraits. 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...
};
▼ 三角形
#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
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;
这个自定义三角形类型将通过调用< code>ComputeTraits(...)
与按位< code > |运算符,如下所示:
myTri.ComputeTraits(MyTri::IDs::AREA | MyTri::IDs::PERIMETER); // Compute area and perimeter
问题就出在这里:假设有< code>Rectangle.h和< code>Pentagon.h,...< code>NthPolygon.h,以同样的方式。
我希望我的每个自定义多边形类型都为其 ComputeTrait(...)
获取强类型参数(所以我用了枚举类),以防止愚蠢的操作采取混合类型的多边形特征,例如
myTri.ComputeTraits(MyTri::IDs::AREA | MyRect::IDs::PERIMETER); // Mixed traits of a triangle and of a rectangle.
所以我想重载< code>|operator,它只接受< code>NthPolygon::IDs:的每个作用域中的未命名枚举...。
我尝试在 NthPolygon::IDs::...
的私有
范围内编写重载模板运算符,但这失败了,因为类内运算符重载始终将第一个参数作为自身:link
使其成为全局作用域的< code >友元也失败了,因为对于每第N个面类,将有不止1个重载的< code>|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;
■问题摘要_________________________
在下面的情况下,如何使模板重载运算符|
仅从特定类中获取参数(未命名枚举)?
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;
}
不确定它是否满足您的要求,但您可能会这样做:
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
}
演示
当将MongoDB的$in子句与Aggregate一起使用时,That在参数数量上有任何最大限制吗? 例如 在id数组中,我可以传递多少id? 目前,我没有遇到任何问题的ids长度达到50,000...但是为了安全起见,我想知道最大限度。 我试着在Mongo doc上搜索,但是什么也没找到。 先谢谢你。
我正在尝试创建一个模板函子,它将使用任意数量的参数作为参数对象和成员函数。我不知道如何用模板正确地编写代码。 如果我使对象::方法没有参数-代码编译。但是有参数-没有。 严重性代码描述项目文件行抑制状态错误C2664'int Builder::运算符()(T
问题内容: 我是Java的新手,我想问这个问题只是为了帮助我更好地理解OOP。 假设我要定义一个名为“小时”的新类。要实例化该类,我们需要指定一个整数以指示该实例的小时数。 因此,当我们在此处定义小时类别时,构造函数的参数应在[0,24)范围内。如果定义了超出此范围的参数,我们如何定义这样的参数?我可以抛出错误吗? 谢谢。 问题答案: 如果您希望 编译器 捕获错误,则可以为小时定义一个枚举,然后将
我试图在类型s. t上专门化一个类。它忽略了给定类型的恒定性。在这种情况下,该类型是一个模板模板参数: 上面的代码在GCC 4.8.4和clang 5.0(with-std=c 11)中都抱怨bar在与匹配FOFType模板参数化的类一起使用时未定义。即使我删除了sfinae参数,仍然无法找到特化。 这个问题的一个例子可以在这里找到:https://godbolt.org/g/Cjci9C.在上面
这行不通,因为premiumStrings::contains可以接受任何对象,而不仅仅是字符串。可以将其替换为<代码>(字符串s)- (具体来说,问题是
我有这样的代码: 这段代码的目的是:如果是或的子类,则将推导为,否则推导为