I am currently writing a library that will sometimes be used alongside OpenCV. Because OpenCV defines a Point_ class that is commonly used in some of the contexts my library will be used in, I'd like to add the option to pass in Point_s as arguments to some of my functions. That said, OpenCV is a pretty heavy library and I'd very much prefer not to depend on it just to get access to it's Point_ class.
Defining my own Point_ identical Point_ class causes the expected multiple definition error.
I considered using a pre-processor macro to check if the OpenCV header containing Point_ has already been included and only define it if it has not been, but I'm concerned that if my libraries header is included first, the multiple definition error will return and this will make my library difficult to use for anyone other than myself.
Is there a way to provide a definition that will only be used if there is not definition anywhere else, and/or will be overridden if one does appear elsewhere?
What you could do is define your library in terms of your point class and optionally generate conversions for the OpenCV
library types if present. Something like this:
#ifdef HAVE_OPENCV
#include <opencv2/opencv.hpp>
#endif
struct my_point
{
double x;
double y;
#ifdef HAVE_OPENCV
my_point(cv::Point2d p): x(p.x), y(p.y) {}
operator cv::Point2d() const { return {x, y}; }
#endif
};
my_point my_function(my_point p)
{
return p;
}
int main()
{
cv::Point2d p;
// automatic conversions happen between OpenCV version
// and your library's version
cv::Point2d q = my_function(p);
}
Because the conversion operators are trivial, inline functions, the compiler will optimize them away completely leaving the code as if no conversion were happening at all.
Optionally (and preferably imo) you could make the conversions explicit which might make for safer code:
struct my_point
{
double x;
double y;
#ifdef HAVE_OPENCV
// make these explicit
explicit my_point(cv::Point2d p): x(p.x), y(p.y) {}
explicit operator cv::Point2d() const { return {x, y}; }
#endif
};
my_point my_function(my_point p)
{
return p;
}
int main()
{
cv::Point2d p;
// Now the library user needs to explicitly ask for
// the conversions to take place
cv::Point2d q = cv::Point2d(my_function(my_point(p)));
}
One solution would be to handle this in your project build configuration: set a preprocessor definition (e.g. COMPILE_WITH_OPENCV
) in your build system. If you're using CMake
, it'll be something like
ADD_DEFINITIONS(-DCOMPILE_WITH_OPENCV)
And in the code:
#if defined COMPILE_WITH_OPENCV
#include "types.hpp" // openCV inlcude
#else
#include "my_types.hpp" // your own Point_ definition
#endif
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With