我正在尝试实施以下API:
geojson::position_t<> point_1{ 10, 12 };
geojson::position_t<> point_2( 11, 13 );
geojson::position_t<> point_3(std::pair<int, int>(12, 14));
geojson::position_t<> line_1{
geojson::position_t<>{ 100, 120 },
geojson::position_t<>{ 110, 130 } };
geojson::position_t<> poly_1{
{ geojson::position_t<>{ 100, 120 }, geojson::position_t<>{ 110, 130 }},
{ geojson::position_t<>{ 101, 121 }, geojson::position_t<>{ 111, 131 }} };
我们的想法是拥有 position_t&lt;&gt; 模板类,其中包含以下属性:
value_type
来识别它是点还是
行value_type get() const {...}
返回点或线类型
取决于是否调用了点或线ctor 我的第一种方法是使用boost :: variant,但我不知道如何获得value_type
并实现get()
方法。
第二次尝试是使用部分模板专业化。但到目前为止,我没有成功。wandbox example
有人可以建议如何实现所需的API吗?
答案 0 :(得分:2)
在C ++ 17中,您可以使用推导出的指南,因此您同时拥有position_t<Point>
和position_t<Line>
,并根据参数构造函数选择正确的指南。
类似的东西:
class Point
{
public:
int x;
int y;
};
class Line
{
public:
Point start;
Point end;
};
template <typename T> class position_t;
template <>
class position_t<Point>
{
public:
position_t(int x, int y) : point{x, y} {}
position_t(const std::pair<int, int>& p) : point{p.first, p.second} {}
const Point& get() const { return point; }
private:
Point point;
};
template <>
class position_t<Line>
{
public:
position_t(const position_t<Point>& start,
const position_t<Point>& end)
: line{start.get(), end.get()}
{}
const Line& get() const { return line; }
private:
Line line;
};
然后是演绎指南
position_t(int, int) -> position_t<Point>;
position_t(std::pair<int, int>) -> position_t<Point>;
position_t(const position_t<Point>&, const position_t<Point>&) -> position_t<Line>;
所以:
geojson::position_t point_1{ 10, 12 }; // geojson::position_t<Point>
geojson::position_t point_2( 11, 13 ); // geojson::position_t<Point>
geojson::position_t point_3(std::pair<int, int>(12, 14)); // geojson::position_t<Point>
geojson::position_t line_1{ // geojson::position_t<Line>
geojson::position_t{ 100, 120 }, // geojson::position_t<Point>
geojson::position_t{ 110, 130 } }; // geojson::position_t<Point>
答案 1 :(得分:1)
以下是两个可选解决方案:
第一个使用标准多态,它使用基类fun showHide(view:View) {
view.visibility = if (view.visibility == View.VISIBLE){
View.INVISIBLE
} else{
View.VISIBLE
}
}
。
第二种方法是使用std :: variant来保存对象。如果使用它,则可以删除基类和虚函数。从评论中读取,您会看到类型扣除规则作为解决方案。是的,我的例子那样工作!
它对于vtable多态性与标记的union作为std :: variant有一些利弊。两者都有可能!
评论:
有一些内部value_type标识它是点还是行
您不需要一些额外的标识符,因为变体本身已包含该类型标记。变量只是一个联合和一个附加数据条目,它跟踪实际分配的类型。正是你想要的!您可以使用GraphicBase
这些标记来调用传递给您传递的函数对象的相应类型的任何函数。 (在我的例子中,我使用通用lambda使调度变得非常容易。
提示: 如果可以进行简单的过载或专业化,请不要考虑SFINAE!
std::visit