Skip to content

Commit 72f789b

Browse files
committed
core: fix type traits
1 parent f626550 commit 72f789b

File tree

9 files changed

+254
-141
lines changed

9 files changed

+254
-141
lines changed

doc/Doxyfile.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ RECURSIVE = YES
107107
EXCLUDE =
108108
EXCLUDE_SYMLINKS = NO
109109
EXCLUDE_PATTERNS = *.inl.hpp *.impl.hpp *_detail.hpp */cudev/**/detail/*.hpp *.m
110-
EXCLUDE_SYMBOLS = cv::DataType<*> int void
110+
EXCLUDE_SYMBOLS = cv::DataType<*> cv::traits::* int void CV__*
111111
EXAMPLE_PATH = @CMAKE_DOXYGEN_EXAMPLE_PATH@
112112
EXAMPLE_PATTERNS = *
113113
EXAMPLE_RECURSIVE = YES

modules/core/include/opencv2/core/cvstd.inl.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ template<typename _Tp, int n> static inline
233233
std::ostream& operator << (std::ostream& out, const Vec<_Tp, n>& vec)
234234
{
235235
out << "[";
236-
if(Vec<_Tp, n>::depth < CV_32F)
236+
if (cv::traits::Depth<_Tp>::value <= CV_32S)
237237
{
238238
for (int i = 0; i < n - 1; ++i) {
239239
out << (int)vec[i] << ", ";

modules/core/include/opencv2/core/mat.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,11 @@ class CV_EXPORTS Mat
15311531
*/
15321532
template<typename _Tp> void push_back(const Mat_<_Tp>& elem);
15331533

1534+
/** @overload
1535+
@param elem Added element(s).
1536+
*/
1537+
template<typename _Tp> void push_back(const std::vector<_Tp>& elem);
1538+
15341539
/** @overload
15351540
@param m Added line(s).
15361541
*/

modules/core/include/opencv2/core/mat.inl.hpp

Lines changed: 128 additions & 121 deletions
Large diffs are not rendered by default.

modules/core/include/opencv2/core/matx.hpp

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,14 @@ In case if C++11 features are avaliable, std::initializer_list can be also used
100100
template<typename _Tp, int m, int n> class Matx
101101
{
102102
public:
103-
enum { depth = DataType<_Tp>::depth,
103+
enum {
104104
rows = m,
105105
cols = n,
106106
channels = rows*cols,
107+
#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED
108+
depth = traits::Type<_Tp>::value,
107109
type = CV_MAKETYPE(depth, channels),
110+
#endif
108111
shortdim = (m < n ? m : n)
109112
};
110113

@@ -259,13 +262,23 @@ template<typename _Tp, int m, int n> class DataType< Matx<_Tp, m, n> >
259262
typedef value_type vec_type;
260263

261264
enum { generic_type = 0,
262-
depth = DataType<channel_type>::depth,
263265
channels = m * n,
264-
fmt = DataType<channel_type>::fmt + ((channels - 1) << 8),
265-
type = CV_MAKETYPE(depth, channels)
266+
fmt = traits::SafeFmt<channel_type>::fmt + ((channels - 1) << 8)
267+
#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED
268+
,depth = DataType<channel_type>::depth
269+
,type = CV_MAKETYPE(depth, channels)
270+
#endif
266271
};
267272
};
268273

274+
namespace traits {
275+
template<typename _Tp, int m, int n>
276+
struct Depth< Matx<_Tp, m, n> > { enum { value = Depth<_Tp>::value }; };
277+
template<typename _Tp, int m, int n>
278+
struct Type< Matx<_Tp, m, n> > { enum { value = CV_MAKETYPE(Depth<_Tp>::value, n*m) }; };
279+
} // namespace
280+
281+
269282
/** @brief Comma-separated Matrix Initializer
270283
*/
271284
template<typename _Tp, int m, int n> class MatxCommaInitializer
@@ -323,9 +336,13 @@ template<typename _Tp, int cn> class Vec : public Matx<_Tp, cn, 1>
323336
{
324337
public:
325338
typedef _Tp value_type;
326-
enum { depth = Matx<_Tp, cn, 1>::depth,
339+
enum {
327340
channels = cn,
328-
type = CV_MAKETYPE(depth, channels)
341+
#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED
342+
depth = Matx<_Tp, cn, 1>::depth,
343+
type = CV_MAKETYPE(depth, channels),
344+
#endif
345+
_dummy_enum_finalizer = 0
329346
};
330347

331348
//! default constructor
@@ -422,13 +439,24 @@ template<typename _Tp, int cn> class DataType< Vec<_Tp, cn> >
422439
typedef value_type vec_type;
423440

424441
enum { generic_type = 0,
425-
depth = DataType<channel_type>::depth,
426442
channels = cn,
427443
fmt = DataType<channel_type>::fmt + ((channels - 1) << 8),
428-
type = CV_MAKETYPE(depth, channels)
444+
#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED
445+
depth = DataType<channel_type>::depth,
446+
type = CV_MAKETYPE(depth, channels),
447+
#endif
448+
_dummy_enum_finalizer = 0
429449
};
430450
};
431451

452+
namespace traits {
453+
template<typename _Tp, int cn>
454+
struct Depth< Vec<_Tp, cn> > { enum { value = Depth<_Tp>::value }; };
455+
template<typename _Tp, int cn>
456+
struct Type< Vec<_Tp, cn> > { enum { value = CV_MAKETYPE(Depth<_Tp>::value, cn) }; };
457+
} // namespace
458+
459+
432460
/** @brief Comma-separated Vec Initializer
433461
*/
434462
template<typename _Tp, int m> class VecCommaInitializer : public MatxCommaInitializer<_Tp, m, 1>

modules/core/include/opencv2/core/persistence.hpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,7 @@ namespace internal
815815
VecWriterProxy( FileStorage* _fs ) : fs(_fs) {}
816816
void operator()(const std::vector<_Tp>& vec) const
817817
{
818-
int _fmt = DataType<_Tp>::fmt;
818+
int _fmt = traits::SafeFmt<_Tp>::fmt;
819819
char fmt[] = { (char)((_fmt >> 8) + '1'), (char)_fmt, '\0' };
820820
fs->writeRaw(fmt, !vec.empty() ? (uchar*)&vec[0] : 0, vec.size() * sizeof(_Tp));
821821
}
@@ -846,7 +846,7 @@ namespace internal
846846
{
847847
size_t remaining = it->remaining;
848848
size_t cn = DataType<_Tp>::channels;
849-
int _fmt = DataType<_Tp>::fmt;
849+
int _fmt = traits::SafeFmt<_Tp>::fmt;
850850
char fmt[] = { (char)((_fmt >> 8)+'1'), (char)_fmt, '\0' };
851851
size_t remaining1 = remaining / cn;
852852
count = count < remaining1 ? count : remaining1;
@@ -999,7 +999,7 @@ void write( FileStorage& fs, const std::vector<DMatch>& vec )
999999
template<typename _Tp> static inline
10001000
void write( FileStorage& fs, const std::vector<_Tp>& vec )
10011001
{
1002-
cv::internal::VecWriterProxy<_Tp, DataType<_Tp>::fmt != 0> w(&fs);
1002+
cv::internal::VecWriterProxy<_Tp, traits::SafeFmt<_Tp>::fmt != 0> w(&fs);
10031003
w(vec);
10041004
}
10051005

@@ -1076,7 +1076,7 @@ void write(FileStorage& fs, const String& name, const DMatch& r )
10761076
template<typename _Tp> static inline
10771077
void write( FileStorage& fs, const String& name, const std::vector<_Tp>& vec )
10781078
{
1079-
cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+(DataType<_Tp>::fmt != 0 ? FileNode::FLOW : 0));
1079+
cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+(traits::SafeFmt<_Tp>::fmt != 0 ? FileNode::FLOW : 0));
10801080
write(fs, vec);
10811081
}
10821082

@@ -1086,7 +1086,7 @@ void write( FileStorage& fs, const String& name, const std::vector< std::vector<
10861086
cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ);
10871087
for(size_t i = 0; i < vec.size(); i++)
10881088
{
1089-
cv::internal::WriteStructContext ws_(fs, name, FileNode::SEQ+(DataType<_Tp>::fmt != 0 ? FileNode::FLOW : 0));
1089+
cv::internal::WriteStructContext ws_(fs, name, FileNode::SEQ+(traits::SafeFmt<_Tp>::fmt != 0 ? FileNode::FLOW : 0));
10901090
write(fs, vec[i]);
10911091
}
10921092
}
@@ -1139,7 +1139,7 @@ void read(const FileNode& node, short& value, short default_value)
11391139
template<typename _Tp> static inline
11401140
void read( FileNodeIterator& it, std::vector<_Tp>& vec, size_t maxCount = (size_t)INT_MAX )
11411141
{
1142-
cv::internal::VecReaderProxy<_Tp, DataType<_Tp>::fmt != 0> r(&it);
1142+
cv::internal::VecReaderProxy<_Tp, traits::SafeFmt<_Tp>::fmt != 0> r(&it);
11431143
r(vec, maxCount);
11441144
}
11451145

@@ -1228,7 +1228,7 @@ FileNodeIterator& operator >> (FileNodeIterator& it, _Tp& value)
12281228
template<typename _Tp> static inline
12291229
FileNodeIterator& operator >> (FileNodeIterator& it, std::vector<_Tp>& vec)
12301230
{
1231-
cv::internal::VecReaderProxy<_Tp, DataType<_Tp>::fmt != 0> r(&it);
1231+
cv::internal::VecReaderProxy<_Tp, traits::SafeFmt<_Tp>::fmt != 0> r(&it);
12321232
r(vec, (size_t)INT_MAX);
12331233
return it;
12341234
}

modules/core/include/opencv2/core/traits.hpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,15 @@
4949
namespace cv
5050
{
5151

52+
//#define OPENCV_TRAITS_ENABLE_DEPRECATED
53+
5254
//! @addtogroup core_basic
5355
//! @{
5456

5557
/** @brief Template "trait" class for OpenCV primitive data types.
5658
59+
@note Deprecated. This is replaced by "single purpose" traits: traits::Type and traits::Depth
60+
5761
A primitive OpenCV data type is one of unsigned char, bool, signed char, unsigned short, signed
5862
short, int, float, double, or a tuple of values of one of these types, where all the values in the
5963
tuple have the same type. Any primitive type from the list can be defined by an identifier in the
@@ -102,10 +106,13 @@ So, such traits are used to tell OpenCV which data type you are working with, ev
102106
not native to OpenCV. For example, the matrix B initialization above is compiled because OpenCV
103107
defines the proper specialized template class DataType\<complex\<_Tp\> \> . This mechanism is also
104108
useful (and used in OpenCV this way) for generic algorithms implementations.
109+
110+
@note Default values were dropped to stop confusing developers about using of unsupported types (see #7599)
105111
*/
106112
template<typename _Tp> class DataType
107113
{
108114
public:
115+
#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED
109116
typedef _Tp value_type;
110117
typedef value_type work_type;
111118
typedef value_type channel_type;
@@ -116,6 +123,7 @@ template<typename _Tp> class DataType
116123
fmt = 0,
117124
type = CV_MAKETYPE(depth, channels)
118125
};
126+
#endif
119127
};
120128

121129
template<> class DataType<bool>
@@ -270,11 +278,14 @@ template<typename _Tp> class DataDepth
270278
};
271279

272280

281+
#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED
273282

274283
template<int _depth> class TypeDepth
275284
{
285+
#ifdef OPENCV_TRAITS_ENABLE_LEGACY_DEFAULTS
276286
enum { depth = CV_USRTYPE1 };
277287
typedef void value_type;
288+
#endif
278289
};
279290

280291
template<> class TypeDepth<CV_8U>
@@ -319,8 +330,68 @@ template<> class TypeDepth<CV_64F>
319330
typedef double value_type;
320331
};
321332

333+
#endif
334+
322335
//! @}
323336

337+
namespace traits {
338+
339+
namespace internal {
340+
#define CV_CREATE_MEMBER_CHECK(X) \
341+
template<typename T> class CheckMember_##X { \
342+
struct Fallback { int X; }; \
343+
struct Derived : T, Fallback { }; \
344+
template<typename U, U> struct Check; \
345+
typedef char CV_NO[1]; \
346+
typedef char CV_YES[2]; \
347+
template<typename U> static CV_NO & func(Check<int Fallback::*, &U::X> *); \
348+
template<typename U> static CV_YES & func(...); \
349+
public: \
350+
typedef CheckMember_##X type; \
351+
enum { value = sizeof(func<Derived>(0)) == sizeof(CV_YES) }; \
352+
};
353+
354+
CV_CREATE_MEMBER_CHECK(fmt)
355+
CV_CREATE_MEMBER_CHECK(type)
356+
357+
} // namespace internal
358+
359+
360+
template<typename T>
361+
struct Depth
362+
{ enum { value = DataType<T>::depth }; };
363+
364+
template<typename T>
365+
struct Type
366+
{ enum { value = DataType<T>::type }; };
367+
368+
/** Similar to traits::Type<T> but has value = -1 in case of unknown type (instead of compiler error) */
369+
template<typename T, bool available = internal::CheckMember_type< DataType<T> >::value >
370+
struct SafeType {};
371+
372+
template<typename T>
373+
struct SafeType<T, false>
374+
{ enum { value = -1 }; };
375+
376+
template<typename T>
377+
struct SafeType<T, true>
378+
{ enum { value = Type<T>::value }; };
379+
380+
381+
template<typename T, bool available = internal::CheckMember_fmt< DataType<T> >::value >
382+
struct SafeFmt {};
383+
384+
template<typename T>
385+
struct SafeFmt<T, false>
386+
{ enum { fmt = 0 }; };
387+
388+
template<typename T>
389+
struct SafeFmt<T, true>
390+
{ enum { fmt = DataType<T>::fmt }; };
391+
392+
393+
} // namespace
394+
324395
} // cv
325396

326397
#endif // OPENCV_CORE_TRAITS_HPP

modules/core/test/test_operations.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ CV_OperationsTest::~CV_OperationsTest() {}
105105
template<typename _Tp> void CV_OperationsTest::TestType(Size sz, _Tp value)
106106
{
107107
cv::Mat_<_Tp> m(sz);
108-
CV_Assert(m.cols == sz.width && m.rows == sz.height && m.depth() == DataType<_Tp>::depth &&
108+
CV_Assert(m.cols == sz.width && m.rows == sz.height && m.depth() == cv::traits::Depth<_Tp>::value &&
109109
m.channels() == DataType<_Tp>::channels &&
110110
m.elemSize() == sizeof(_Tp) && m.step == m.elemSize()*m.cols);
111111
for( int y = 0; y < sz.height; y++ )

modules/python/src2/cv2.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,7 +1076,7 @@ template<typename _Tp> struct pyopencvVecConverter
10761076
int i, j, n = (int)PySequence_Fast_GET_SIZE(seq);
10771077
value.resize(n);
10781078

1079-
int type = DataType<_Tp>::type;
1079+
int type = traits::Type<_Tp>::value;
10801080
int depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type);
10811081
PyObject** items = PySequence_Fast_ITEMS(seq);
10821082

@@ -1159,7 +1159,9 @@ template<typename _Tp> struct pyopencvVecConverter
11591159
{
11601160
if(value.empty())
11611161
return PyTuple_New(0);
1162-
Mat src((int)value.size(), DataType<_Tp>::channels, DataType<_Tp>::depth, (uchar*)&value[0]);
1162+
int type = traits::Type<_Tp>::value;
1163+
int depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type);
1164+
Mat src((int)value.size(), channels, depth, (uchar*)&value[0]);
11631165
return pyopencv_from(src);
11641166
}
11651167
};

0 commit comments

Comments
 (0)