boost::geometry provides for planar Cartesian coordinates two classes to define a point, using a given floating point type (double, float, ...):
(assume namespace bg = boost::geometry;
in the following)
With FPT being the desired floating point type (float, double, ...):
bg::model::point<FPT, 2, bg::cs::cartesian> pt1;
bg::model::d2::point_xy<FPT> pt2;
(unrelated note: the second type is being inherited from the first one).
Now say I want a constructor taking a boost point as single argument for some class. How do I write this, so that it will be selected only for these two types (because there are other single argument constructors in the class)?
For example, say I have this, where the constructor for boost points needs to be "sfinaed":
template<typename FPT>
struct Point
{
FPT x,y;
template<typename BPT> // Boost Point Type
Point( const BPT& in )
{ /* code here */ }
template<typename T> // other type
Point( const T& in )
{ /* code here */ }
};
I read here that the boost point classes must comply to a concept that states that:
there must be a specialization of traits::tag, defining point_tag as type
So I tried this (live here) but there must be something I am missing, because it fails to build, with the classical
template argument deduction/substitution failed
template<typename FPT> // Floating Point Type
struct Point
{
FPT x,y;
template<
typename BPT, // Boost Point Type
typename std::enable_if<
std::is_same<
bg::traits::tag<BPT>,
bg::point_tag
>::value,
BPT
>::type* = nullptr
>
Point( const BPT& pt ):
x{ bg::get<0>(pt) }, // maybe add some static cast here
y{ bg::get<1>(pt) }
{}
};
int main()
{
bg::model::point<double, 2, bg::cs::cartesian> pt1;
bg::model::d2::point_xy<double> pt2;
Point<float> p1(pt1);
Point<double> p2(pt2);
}
Those errors are still particularly difficult for me to track down... Any idea?
Well, constructors don't have return types didn't you know? ;)
Here you go:
template<typename FPT> // Floating Point Type
struct Point
{
FPT x,y;
template<class BPT>
Point( const BPT& pt, typename std::enable_if<
std::is_same<bg::traits::tag<BPT>, bg::point_tag>::value
>::type* = nullptr)
:
x{ boost::geometry::get<0>(pt) }, // maybe add some static cast here
y{ boost::geometry::get<1>(pt) }
{}
template<class Other>
Point(const Other&) : x{0}, y{0} {}
};
Note: If C++20 is an option, concepts would be the ideal solution rather than SFINAE.