Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

int to proper enum type #12288

Closed
wants to merge 22 commits into from
Closed

Conversation

cv3d
Copy link
Contributor

@cv3d cv3d commented Aug 23, 2018

TESTING... DO NOT MERGE!
Merge with opencv/opencv_contrib#1730 and opencv/opencv_extra#515

This pullrequest changes

There are hundreds of unnamed enums, and they are being passed as int in the C++ interface.
In order to avoid passing a wrong value, and to maintain good practices, the hope is to name most of these enums, and change the int arguments into the proper enum types wherever possible.

Newly introduced enums

  • ElemType for handling the depth and channels of matrix elements (Produced by DataType<T>::type and traits::Type<T>::value)
  • ElemDepth for handling the depth of matrix elements (Produced by DataDepth<T>::type and traits::Depth<T>::value)
  • MagicFlag for handling the mixed magic values of ElemType, AccessFlag and _InputArray::KindFlag

Flag enums

  • AccessFlag for unnamed enum having ACCESS_READ as first member
  • [Converted DrawMatchesFlags struct to enum struct] DrawMatchesFlags::unnamed enum having DEFAULT as first member
  • MemoryFlag for UMatData::unnamed enum having COPY_ON_MAP as first member
  • KindFlag for _InputArray::unnamed enum having KIND_SHIFT as first member

Mode enums

  • DescriptorType for AKAZE::unnamed enum having DESCRIPTOR_KAZE_UPRIGHT as first member
  • DetectorType for AgastFeatureDetector::unnamed enum having AGAST_5_8 as first member
  • FeatureType for CvFeatureParams::unnamed enum having HAAR as first member
  • DetectorType for FastFeatureDetector::unnamed enum having TYPE_5_8 as first member
  • MatcherType for DescriptorMatcher::unnamed enum having FLANNBASED as first member
  • FormatType for Formatter::unnamed enum having FMT_DEFAULT as first member
  • HistogramNormType for HOGDescriptor::unnamed enum having L2Hys as the only member
  • [Converted to static const NormTypes] for Hamming::unnamed enum having normType as the only member
  • [Converted to static const NormTypes] for SL2::unnamed enum having normType as the only member
  • [Converted to static const NormTypes] for L2::unnamed enum having normType as the only member
  • [Converted to static const NormTypes] for L1::unnamed enum having normType as the only member
  • [Converted to static const int] for Mat::unnamed enum having MAGIC_MASK as first member
  • [Converted to static const int] for Mat::unnamed enum having MAGIC_VAL as first member
  • [Converted to static const int] for SparseMat::unnamed enum having MAGIC_VAL as first member
  • [Converted to static const int] for UMat::unnamed enum having MAGIC_MASK as first member
  • [Converted to static const int] for UMat::unnamed enum having MAGIC_VAL as first member
  • DiffusivityType for KAZE::unnamed enum having DIFF_PM_G1 as first member
  • ScoreType for ORB::unnamed enum having kBytes as first member, and kBytes become a static const int
  • [Converted Param struct to enum struct] Param::unnamed enum having INT as first member
  • [Converted to static const int] for cuda::FastFeatureDetector::unnamed enum having LOCATION_ROW as first member
  • [Removed the enum] for cuda::HOG::unnamed enum having DESCR_FORMAT_ROW_BY_ROW as first member
  • [Converted to static const int] for cuda::ORB::unnamed enum having X_ROW as first member
  • NormalizationType for xfeatures2d::DAISY::unnamed enum having NRM_NONE as first member
  • [Converted to static const int] for xfeatures2d::FREAK::unnamed enum having NB_SCALES as first member
  • DepthMask for _OutputArray::unnamed enum having DEPTH_MASK_8U as first member

Tasks list

  • ❔ for unnamed enum having CALIB_CB_ADAPTIVE_THRESH as first member
  • ❔ for unnamed enum having CALIB_CB_SYMMETRIC_GRID as first member
  • ❔ for unnamed enum having CALIB_USE_INTRINSIC_GUESS as first member
  • ❔ for unnamed enum having CAP_INTELPERC_DEPTH_GENERATOR as first member
  • ❔ for unnamed enum having CAP_INTELPERC_DEPTH_MAP as first member
  • ❔ for unnamed enum having CAP_OPENNI_DEPTH_GENERATOR as first member
  • ❔ for unnamed enum having CAP_OPENNI_DEPTH_MAP as first member
  • ❔ for unnamed enum having CAP_OPENNI_IMAGE_GENERATOR_PRESENT as first member
  • ❔ for unnamed enum having CAP_OPENNI_VGA_30HZ as first member
  • ❔ for unnamed enum having CAP_PROP_DC1394_OFF as first member
  • ❔ for unnamed enum having CAP_PROP_GIGA_FRAME_OFFSET_X as first member
  • ❔ for unnamed enum having CAP_PROP_GPHOTO2_PREVIEW as first member
  • ❔ for unnamed enum having CAP_PROP_GSTREAMER_QUEUE_LENGTH as first member
  • ❔ for unnamed enum having CAP_PROP_IMAGES_BASE as first member
  • ❔ for unnamed enum having CAP_PROP_INTELPERC_PROFILE_COUNT as first member
  • ❔ for unnamed enum having CAP_PROP_IOS_DEVICE_FOCUS as first member
  • ❔ for unnamed enum having CAP_PROP_OPENNI_OUTPUT_MODE as first member
  • ❔ for unnamed enum having CAP_PROP_PVAPI_MULTICASTIP as first member
  • ❔ for unnamed enum having CAP_PROP_XI_DOWNSAMPLING as first member
  • ❔ for unnamed enum having CAP_PVAPI_DECIMATION_OFF as first member
  • ❔ for unnamed enum having CAP_PVAPI_FSTRIGMODE_FREERUN as first member
  • ❔ for unnamed enum having CAP_PVAPI_PIXELFORMAT_MONO8 as first member
  • ❔ for unnamed enum having CASCADE_DO_CANNY_PRUNING as first member
  • ❔ for unnamed enum having FM_7POINT as first member
  • ❔ for unnamed enum having INPAINT_NS as first member
  • ❔ for unnamed enum having LDR_SIZE as first member
  • ❔ for unnamed enum having LMEDS as first member
  • ❔ for unnamed enum having MOTION_TRANSLATION as first member
  • ❔ for unnamed enum having NORMAL_CLONE as first member
  • ❔ for unnamed enum having OPTFLOW_USE_INITIAL_FLOW as first member
  • ❔ for unnamed enum having RECURS_FILTER as first member
  • ❔ for unnamed enum having SOLVEPNP_ITERATIVE as first member
  • ❔ for RNG::unnamed enum having UNIFORM as first member
  • ❔ for StereoBM::unnamed enum having PREFILTER_NORMALIZED_RESPONSE as first member
  • ❔ for StereoMatcher::unnamed enum having DISP_SHIFT as first member
  • ❔ for StereoSGBM::unnamed enum having MODE_SGBM as first member
  • ❔ for Stitcher::unnamed enum having ORIG_RESOL as first member
  • ❔ for Subdiv2D::unnamed enum having NEXT_AROUND_ORG as first member
  • ❔ for Subdiv2D::unnamed enum having PTLOC_ERROR as first member
  • ❔ for TrackerSamplerCS::unnamed enum having MODE_POSITIVE as first member
  • ❔ for TrackerSamplerCSC::unnamed enum having MODE_INIT_POS as first member
  • ❔ for bioinspired::unnamed enum having RETINA_COLOR_RANDOM as first member
  • ❔ for detail::Blender::unnamed enum having NO as first member
  • ❔ for detail::ExposureCompensator::unnamed enum having NO as first member
  • ❔ for detail::Timelapser::unnamed enum having AS_IS as first member
  • ❔ for fisheye::unnamed enum having CALIB_USE_INTRINSIC_GUESS as first member
  • ❔ for ft::unnamed enum having LINEAR as first member
  • ❔ for ft::unnamed enum having ONE_STEP as first member
  • ❔ for line_descriptor::DrawLinesMatchesFlags::unnamed enum having DEFAULT as first member
  • ❔ for ml::EM::unnamed enum having DEFAULT_NCLUSTERS as first member
  • ❔ for ml::EM::unnamed enum having START_E_STEP as first member
  • ❔ for multicalib::MultiCameraCalibration::unnamed enum having PINHOLE as first member
  • ❔ for ocl::Device::unnamed enum having EXEC_KERNEL as first member
  • ❔ for ocl::Device::unnamed enum having FP_DENORM as first member
  • ❔ for ocl::Device::unnamed enum having NO_CACHE as first member
  • ❔ for ocl::Device::unnamed enum having NO_LOCAL_MEM as first member
  • ❔ for ocl::Device::unnamed enum having TYPE_DEFAULT as first member
  • ❔ for ocl::Device::unnamed enum having UNKNOWN_VENDOR as first member
  • ❔ for ocl::KernelArg::unnamed enum having LOCAL as first member
  • ❔ for omnidir::unnamed enum having CALIB_USE_GUESS as first member
  • ❔ for omnidir::unnamed enum having RECTIFY_PERSPECTIVE as first member
  • ❔ for omnidir::unnamed enum having XYZRGB as first member
  • ❔ for optflow::DISOpticalFlow::unnamed enum having PRESET_ULTRAFAST as first member
  • ❔ for rgbd::Odometry::unnamed enum having ROTATION as first member
  • ❔ for rgbd::OdometryFrame::unnamed enum having CACHE_SRC as first member
  • ❔ for structured_light::unnamed enum having DECODE_3D_UNDERWORLD as first member
  • ❔ for structured_light::unnamed enum having FTP as first member
  • ❔ for text::unnamed enum having ERFILTER_NM_RGBLGrad as first member
  • ❔ for text::unnamed enum having OCR_LEVEL_WORD as first member
  • ❔ for viz::KeyboardEvent::unnamed enum having NONE as first member
  • ❔ for viz::Mesh::unnamed enum having LOAD_AUTO as first member
  • ❔ for viz::WTrajectory::unnamed enum having FRAMES as first member

Current issues

  • [need remove from public API] FileStorage::unnamed enum having UNDEFINED as first member
  • A lot of static_cast<MagicFlag>() are utilized now. Proper operators needs to get enabled
  • Converteing HOGDescriptor::unnamed enum having DEFAULT_NLEVELS as the only member to to static const int causes some Java test to fail
    [javac] /build/precommit_android/build/android_test/src/org/opencv/test/objdetect/HOGDescriptorTest.java:204: error: cannot find symbol [javac] assertEquals(HOGDescriptor.DEFAULT_NLEVELS, hog.get_nlevels()); [javac] ^ [javac] symbol: variable DEFAULT_NLEVELS [javac] location: class HOGDescriptor [javac] Note: Some input files use unchecked or unsafe operations. [javac] Note: Recompile with -Xlint:unchecked for details. [javac] 1 error
force_builders=Custom,linux32,win32,windows_vc15,ARMv7,ARMv8,Android pack
docker_image:Custom=ubuntu-cuda:16.04
docker_image:Docs=docs-js

@alalek
Copy link
Member

alalek commented Aug 23, 2018

enum ACCESS_FLAG

Use 'CamelCase' for types / enums. All capitals letters are reserved for macro / constants itself.

BTW, This is not regular (simple) enum. This is "bit-set" enum, for example: ACCESS_READ | ACCESS_FAST is valid parameter.

@cv3d cv3d force-pushed the improvements/enum_interface branch from adafff3 to 2e2892d Compare August 23, 2018 10:25
@alalek
Copy link
Member

alalek commented Aug 23, 2018

Some design work is required to resolve "enum" handling.

Enum categories

I see these classes of enums used in OpenCV:

  • regular enums with exclusive values (usually has "Mode" suffix, but avoid "Modes"): one value for parameter is allowed only.
  • bit-set enums ("Flag"/"Flags" suffix): OR-ed values are allowed. To avoid verbose "static_cast(..)" we can try this:
    • perhaps we should add enum entries for some actively used cased like :
      • ACCESS_RW = ACCESS_READ | ACCESS_WRITE
      • ACCESS_READ_FAST = ACCESS_READ | ACCESS_FAST
    • alternatively we can try to overload operator | () (Will it work?). But it is C++ only. What is about Python / Java?
  • videoio's CAP_PROP_* enums. There are many enums, but they are passed to single function (.get() method). No idea about C++, but in Python we can group them into single enum type:
    • VideoCaptureProperty.CAP_PROP_GSTREAMER_QUEUE_LENGTH
    • VideoCaptureProperty.CAP_PROP_IMAGES_BASE
  • enums in classes. Some of them are used as a constants for native int parameters, like DEFAULT_NLEVELS. No need to name them. Perhaps some of these enums should be replaced to static const int DEFAULT_NLEVELS = 64; (there are no more issues with modern compilers anymore) and bindings generator should know them

Handling enums in Python.

Currently all enums are "int" contants in Python. This approach is not safe and error prone.
It would be nice to introduce real enum types in Python.

Unfortunately, only Python 3.6+ have "native" enum types:

from enum import Enum
class AccessFlag(Enum):
    ACCESS_READ = 1 << 24
    ACCESS_WRITE = 2 << 24
    ACCESS_RW = 3 << 24
    ...

We should emulate this for other Python versions somehow.

Usage compatibility between C++ and Python

In C++ enum type is not used for accessing of enum value (added to namespace/class): cv::ACCESS_READ
In Python it is required to use enum name: cv.AccessFlag.ACCESS_READ

So probably we should duplicate enum values into current module to save compatibility with existed Python code and keep similarity between C++/Python code:

class AccessFlag(Enum):
    ACCESS_READ = 1 << 24
    ...

ACCESS_READ = AccessFlag.ACCESS_READ
ACCESS_WRITE = AccessFlag.ACCESS_WRITE

@cv3d
Copy link
Contributor Author

cv3d commented Aug 23, 2018

alternatively we can try to overload operator | () (Will it work?)

operator | () will not work, as it causes issues with Eigen library. Can we define it only for cv namespace by any chance?
As for link you provided, it seems to refer to operator |= (), which I already defined.

@cv3d cv3d force-pushed the improvements/enum_interface branch 6 times, most recently from 8fd21a8 to 1cf6d48 Compare August 23, 2018 16:48
@hrnr
Copy link
Contributor

hrnr commented Aug 23, 2018

Thanks for revisiting enums for OpenCV 4 this was bothering me too.

  • enums in classes.

some of those enums in classes are there for encapsulation. However they seem to cause problems for Python wrapper (#10681). Could this be supported for wrapping? Should those enums be moved to be consistent with rest of the OpenCV?

Usage compatibility between C++ and Python

Python enums are basically enum class in C++11. Making all enums enum class would be, however, a big disaster (without any backward compatibility stuff).

operator | () will not work, as it causes issues with Eigen library.

I can't see why that should cause any issues for Eigen. What was the exact error?

If possible, I think introducing this operator for "flags" enums like this would be quite an easy and backward-compatible way. Of cause wrap this in macro, so we can easily add it for enums that need it. Like CV_FLAGS_ENUM(AccessFlag).

@@ -63,6 +63,16 @@ namespace cv
//! @addtogroup core_basic
//! @{

//////////////////////////////// Enum operators //////////////////////////////

template<typename T, typename std::enable_if< std::is_enum<T>::value >::type* = nullptr>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe consider adding this only for "flags" enums on per-enum basis. For "mode" enums this does not make sense. It could confuse users to use this to pass OR-ed values where it should not be used.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also operator | () is needed too.

@cv3d
Copy link
Contributor Author

cv3d commented Aug 23, 2018

I can't see why that should cause any issues for Eigen. What was the exact error?

If I define:

template<typename T, typename std::enable_if< std::is_enum<T>::value >::type* = nullptr>
static T operator|(const T& a, const T& b)
{
    typedef typename std::underlying_type<T>::type EnumType;
    return static_cast<T>(static_cast<EnumType>(a) | static_cast<EnumType>(b));
}

Then the following errors occurs, and while I can manage the first bullet, I do not know how to fix the second:

  • All enum definitions in the form ACCESS_READ_FAST = ACCESS_READ | ACCESS_FAST results in error C2057: expected constant expression
  • The type UpperBidiagonalization::DiagVectorType results in error C2975: '_Options' : invalid template argument for 'Eigen::Matrix', expected compile-time constant expression

@cv3d cv3d force-pushed the improvements/enum_interface branch from 1cf6d48 to a69f060 Compare August 23, 2018 18:33
@alalek
Copy link
Member

alalek commented Aug 23, 2018

Just don't use templates. Separate operator definition for each "flags" enum, something like this:

// in namespace cv
static inline AccessFlags operator | (const AccessFlags& a, const AccessFlags& b)
{
    return (AccessFlags)((int)a | (int)b);
}
// this should work now: AccessFlags flags = ACCESS_READ | ACCESS_WRITE;

CV_FLAGS_ENUM(AccessFlag)

I like this idea to declare multiple operators.

@hrnr
Copy link
Contributor

hrnr commented Aug 23, 2018

that seems to be the same issue. constexpr should fix that.

However, I think it is not a good idea to declare templated operator |() for all enums. Even though the operator is declared in cv namespace it can be ADL-resolved for user code. That is what happened for Eigen.

@alalek exactly!

@cv3d cv3d force-pushed the improvements/enum_interface branch from a69f060 to 80d8839 Compare August 23, 2018 19:44
@hrnr
Copy link
Contributor

hrnr commented Aug 23, 2018

To resolve ACCESS_READ_FAST = ACCESS_READ | ACCESS_FAST error I think you need to make the operator constexpr, so it can be used in constant expressions.

To be specific:

#define CV_FLAGS_ENUM(EnumType)                                                \
  static constexpr EnumType operator|(const EnumType &a, const EnumType &b) {  \
    typedef typename std::underlying_type<EnumType>::type u_type;              \
    return static_cast<EnumType>(static_cast<u_type>(a) |                      \
                                 static_cast<u_type>(b));                      \
  }

(you should add more operators for &, |=, &= etc.)

Then declare

enum AccessFlag { ACCESS_READ=1<<24, ACCESS_WRITE=1<<25,
 ACCESS_RW=3<<24, ACCESS_MASK=ACCESS_RW, ACCESS_FAST=1<<26,
 ACCESS_READ_FAST = ACCESS_READ | ACCESS_FAST };
CV_FLAGS_ENUM(AccessFlag);

constexpr allows to use the operator in constant expressions.

This approach allows us to declare the operator only for enums where it makes sense.

BTW: I'm not sure if we need ACCESS_READ_FAST really when we have working operator |(), but it possible to define it in this way with this approach.

Copy link
Contributor Author

@cv3d cv3d left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about this solution? I guess it is mature enough, is not it?

template<typename T, typename T2, typename std::enable_if< std::is_enum<T>::value
&& T::CV_FLAGS_ENUM == T::CV_FLAGS_ENUM >::type* = nullptr>
static T operator|(const T2& a, const T& b)
{
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about utilizing SFINAE and introducing CV_FLAGS_ENUM in the flag-based enums? I guess this solution is elegant enough.

ACCESS_RW=3<<24, ACCESS_MASK=ACCESS_RW, ACCESS_FAST=1<<26 };
enum AccessFlag { ACCESS_READ=1<<24, ACCESS_WRITE=1<<25,
ACCESS_RW=3<<24, ACCESS_MASK=ACCESS_RW, ACCESS_FAST=1<<26,
CV_FLAGS_ENUM = ACCESS_READ };

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you can see, CV_FLAGS_ENUM is introduced to enable bitwise operators, and it can take any value, and in this case, it is assigned ACCESS_READ for safety against ignorant users.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool. I think that would work.

The obvious disadvantage is that we have extra CV_FLAGS_ENUM in every flags enum and in documentation etc. Also in my experience widely used SFINAE can affect compilation times pretty badly.

Therefore, I would prefer the solution above, but this is certainly workable too. If you want to go with this, I suggest to add constexpr to allow using it in constant expressions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

constexpr is available from Visual Studio 2015.
Do we really want to drop support of Visual Studio 2013? It is still widely used...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think OpenCV 4 will be C++11 as per OE-4

@@ -15,7 +15,7 @@ namespace cv {
Mat _InputArray::getMat_(int i) const
{
int k = kind();
int accessFlags = flags & ACCESS_MASK;
AccessFlag accessFlags = flags & ACCESS_MASK;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hrnr The problem with the macro-based solution is that it cannot handle two types T1, T2, thus the above expression would not compile since flags is int. Of couse we can introduce cast in such cases, but this might break user code as well. The only solution that seems to work with minimal changes is a template-based one. Accordingly, I would like to go with my proposal, at least for the time-being.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is about this?

AccessFlag operator & (const int a, const AccessFlag& b)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also would work, but I am not sure if int is the only type utilized with bitwise operations (how about long?), and I do not think we want to provide all the variants. On the other hand, the template-based solution referenced above is just doing that with minimal effort, I guess.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int, long and other helper operators can be placed under CV_FLAGS_ENUM(enumType) macro:

enum AccessFlag { ... };
CV_FLAGS_ENUM(AccessFlag);  // define helper operators here

It can be added for each bit-set/flags enum types.

@cv3d cv3d force-pushed the improvements/enum_interface branch from 80d8839 to 25c0bd6 Compare August 23, 2018 22:10
CV_FLAGS_ENUM_XOR_EQ(EnumType, EnumType); \
CV_FLAGS_ENUM_OR_EQ (EnumType, int); \
CV_FLAGS_ENUM_AND_EQ(EnumType, int); \
CV_FLAGS_ENUM_XOR_EQ(EnumType, int); \

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alalek @hrnr I am glad there is no limit for macros length ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although it is hard to maintain, I need to admit that it is looks beautiful and have optimal performance.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work. Keep going!

I think that int is enough for the overloads as enums convert implicitly to ints (we have only int enums). Moreover, I think we should get rid of those overloads one day to disallow AccessFlags flags = cv::RANSAC | ACCESS_WRITE;. Casts would need to be added to some places though.

Copy link
Contributor Author

@cv3d cv3d Aug 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The good news is, if cv::RANSAC is not an int, AccessFlags flags = cv::RANSAC | ACCESS_WRITE would not work.
That is another reason to avoid using int, and use enum types instead.

@cv3d cv3d force-pushed the improvements/enum_interface branch from 25c0bd6 to cff9c46 Compare August 24, 2018 07:46
if (!(arg.flags & KernelArg::READ_ONLY))
accessFlags &= ~ACCESS_READ;
if (!(arg.flags & KernelArg::WRITE_ONLY))
accessFlags &= ~ACCESS_WRITE;
bool ptronly = (arg.flags & KernelArg::PTR_ONLY) != 0;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alalek @hrnr We do not have ACCESS_NONE to write something like ((arg.flags & KernelArg::READ_ONLY) ? ACCESS_READ : ACCESS_NONE) | ((arg.flags & KernelArg::WRITE_ONLY) ? ACCESS_WRITE : ACCESS_NONE) and even the ACCESS_MASK is not covering the FAST_ACCESS bit...
In this case, all I can think of is the negative logic. Is there any better idea to do this more efficiently?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For any "flags" enum, "0" is default "none" value.

I would like to avoid introducing separate meaningless enum value like ACCESS_NONE. Perhaps we can write here (AccessFlag)0 instead.

It is better to drop "negative logic" in code, like your suggestion.

Alternatively we can try to overload operator - () for "flag" enums (but we should make it safe).

@cv3d cv3d force-pushed the improvements/enum_interface branch 3 times, most recently from e6f1bbc to 20517ce Compare August 24, 2018 13:19

// Exposes the listed 5 members of the enum class AccessFlag to the current namespace
CV_ENUM_CLASS_EXPOSE(AccessFlag, 5, ACCESS_READ, ACCESS_WRITE, ACCESS_RW, ACCESS_MASK, ACCESS_FAST);
@endcode
Copy link
Contributor Author

@cv3d cv3d Aug 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making all enums enum class would be, however, a big disaster (without any backward compatibility stuff).

I managed to get C++11 enum classes working with backwards compatibility and minimal changes.

Basically, instead of:

enum xyz { m1, m2, m3};

one would define:

enum class xyz { m1, m2, m3};
CV_ENUM_CLASS_EXPOSE(xyz, m1, m2, m3);

and in case it is a flag enum, then CV_ENUM_FLAGS_CLASS(AccessFlag); instead of CV_ENUM_FLAGS(AccessFlag); would do the trick.

Only Python module still have issues with that, but I believe I can work around that as well.
@alalek @hrnr Shall I consider changing the enums into enum classes?

@cv3d cv3d force-pushed the improvements/enum_interface branch from 20517ce to a01d44a Compare August 24, 2018 13:32
@cv3d cv3d force-pushed the improvements/enum_interface branch 7 times, most recently from 5bc7784 to 794e88d Compare September 20, 2018 14:38
@cv3d cv3d force-pushed the improvements/enum_interface branch from 794e88d to 65b4ad7 Compare September 20, 2018 15:09
@vpisarev vpisarev closed this Oct 7, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature future This issue can't be fixed during restrictions of the compatibility requirements RFC
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants