From 15aee09c7f202f6f3797c2d4edc4d73ab45fd73e Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 6 Sep 2018 23:05:40 +0000 Subject: [PATCH 1/3] core: replace cv::Ptr implementation => std::shared_ptr --- modules/core/include/opencv2/core/cvstd.hpp | 307 +------------- .../include/opencv2/core/cvstd_wrapper.hpp | 147 +++++++ modules/core/include/opencv2/core/ptr.inl.hpp | 375 ------------------ 3 files changed, 149 insertions(+), 680 deletions(-) create mode 100644 modules/core/include/opencv2/core/cvstd_wrapper.hpp delete mode 100644 modules/core/include/opencv2/core/ptr.inl.hpp diff --git a/modules/core/include/opencv2/core/cvstd.hpp b/modules/core/include/opencv2/core/cvstd.hpp index 69846f7ab6..038ccaa7e2 100644 --- a/modules/core/include/opencv2/core/cvstd.hpp +++ b/modules/core/include/opencv2/core/cvstd.hpp @@ -78,6 +78,8 @@ namespace cv using std::log; } +#include "cvstd_wrapper.hpp" + namespace cv { //! @addtogroup core_utils @@ -138,314 +140,11 @@ public: //! @} core_utils -//! @cond IGNORED - -namespace detail -{ - -// Metafunction to avoid taking a reference to void. -template -struct RefOrVoid { typedef T& type; }; - -template<> -struct RefOrVoid{ typedef void type; }; - -template<> -struct RefOrVoid{ typedef const void type; }; - -template<> -struct RefOrVoid{ typedef volatile void type; }; - -template<> -struct RefOrVoid{ typedef const volatile void type; }; - -// This class would be private to Ptr, if it didn't have to be a non-template. -struct PtrOwner; - -} - -template -struct DefaultDeleter -{ - void operator () (Y* p) const; -}; - //! @endcond //! @addtogroup core_basic //! @{ -/** @brief Template class for smart pointers with shared ownership - -A Ptr\ pretends to be a pointer to an object of type T. Unlike an ordinary pointer, however, the -object will be automatically cleaned up once all Ptr instances pointing to it are destroyed. - -Ptr is similar to boost::shared_ptr that is part of the Boost library -() and std::shared_ptr from -the [C++11](http://en.wikipedia.org/wiki/C++11) standard. - -This class provides the following advantages: -- Default constructor, copy constructor, and assignment operator for an arbitrary C++ class or C - structure. For some objects, like files, windows, mutexes, sockets, and others, a copy - constructor or an assignment operator are difficult to define. For some other objects, like - complex classifiers in OpenCV, copy constructors are absent and not easy to implement. Finally, - some of complex OpenCV and your own data structures may be written in C. However, copy - constructors and default constructors can simplify programming a lot. Besides, they are often - required (for example, by STL containers). By using a Ptr to such an object instead of the - object itself, you automatically get all of the necessary constructors and the assignment - operator. -- *O(1)* complexity of the above-mentioned operations. While some structures, like std::vector, - provide a copy constructor and an assignment operator, the operations may take a considerable - amount of time if the data structures are large. But if the structures are put into a Ptr, the - overhead is small and independent of the data size. -- Automatic and customizable cleanup, even for C structures. See the example below with FILE\*. -- Heterogeneous collections of objects. The standard STL and most other C++ and OpenCV containers - can store only objects of the same type and the same size. The classical solution to store - objects of different types in the same container is to store pointers to the base class (Base\*) - instead but then you lose the automatic memory management. Again, by using Ptr\ instead - of raw pointers, you can solve the problem. - -A Ptr is said to *own* a pointer - that is, for each Ptr there is a pointer that will be deleted -once all Ptr instances that own it are destroyed. The owned pointer may be null, in which case -nothing is deleted. Each Ptr also *stores* a pointer. The stored pointer is the pointer the Ptr -pretends to be; that is, the one you get when you use Ptr::get or the conversion to T\*. It's -usually the same as the owned pointer, but if you use casts or the general shared-ownership -constructor, the two may diverge: the Ptr will still own the original pointer, but will itself point -to something else. - -The owned pointer is treated as a black box. The only thing Ptr needs to know about it is how to -delete it. This knowledge is encapsulated in the *deleter* - an auxiliary object that is associated -with the owned pointer and shared between all Ptr instances that own it. The default deleter is an -instance of DefaultDeleter, which uses the standard C++ delete operator; as such it will work with -any pointer allocated with the standard new operator. - -However, if the pointer must be deleted in a different way, you must specify a custom deleter upon -Ptr construction. A deleter is simply a callable object that accepts the pointer as its sole -argument. For example, if you want to wrap FILE, you may do so as follows: -@code - Ptr f(fopen("myfile.txt", "w"), fclose); - if(!f) throw ...; - fprintf(f, ....); - ... - // the file will be closed automatically by f's destructor. -@endcode -Alternatively, if you want all pointers of a particular type to be deleted the same way, you can -specialize DefaultDeleter::operator() for that type, like this: -@code - namespace cv { - template<> void DefaultDeleter::operator ()(FILE * obj) const - { - fclose(obj); - } - } -@endcode -For convenience, the following types from the OpenCV C API already have such a specialization that -calls the appropriate release function: -- CvCapture -- CvFileStorage -- CvHaarClassifierCascade -- CvMat -- CvMatND -- CvMemStorage -- CvSparseMat -- CvVideoWriter -- IplImage -@note The shared ownership mechanism is implemented with reference counting. As such, cyclic -ownership (e.g. when object a contains a Ptr to object b, which contains a Ptr to object a) will -lead to all involved objects never being cleaned up. Avoid such situations. -@note It is safe to concurrently read (but not write) a Ptr instance from multiple threads and -therefore it is normally safe to use it in multi-threaded applications. The same is true for Mat and -other C++ OpenCV classes that use internal reference counts. -*/ -template -struct Ptr -{ - /** Generic programming support. */ - typedef T element_type; - - /** The default constructor creates a null Ptr - one that owns and stores a null pointer. - */ - Ptr(); - - /** - If p is null, these are equivalent to the default constructor. - Otherwise, these constructors assume ownership of p - that is, the created Ptr owns and stores p - and assumes it is the sole owner of it. Don't use them if p is already owned by another Ptr, or - else p will get deleted twice. - With the first constructor, DefaultDeleter\() becomes the associated deleter (so p will - eventually be deleted with the standard delete operator). Y must be a complete type at the point - of invocation. - With the second constructor, d becomes the associated deleter. - Y\* must be convertible to T\*. - @param p Pointer to own. - @note It is often easier to use makePtr instead. - */ - template - explicit Ptr(Y* p); - - /** @overload - @param d Deleter to use for the owned pointer. - @param p Pointer to own. - */ - template - Ptr(Y* p, D d); - - /** - These constructors create a Ptr that shares ownership with another Ptr - that is, own the same - pointer as o. - With the first two, the same pointer is stored, as well; for the second, Y\* must be convertible - to T\*. - With the third, p is stored, and Y may be any type. This constructor allows to have completely - unrelated owned and stored pointers, and should be used with care to avoid confusion. A relatively - benign use is to create a non-owning Ptr, like this: - @code - ptr = Ptr(Ptr(), dont_delete_me); // owns nothing; will not delete the pointer. - @endcode - @param o Ptr to share ownership with. - */ - Ptr(const Ptr& o); - - /** @overload - @param o Ptr to share ownership with. - */ - template - Ptr(const Ptr& o); - - /** @overload - @param o Ptr to share ownership with. - @param p Pointer to store. - */ - template - Ptr(const Ptr& o, T* p); - - /** The destructor is equivalent to calling Ptr::release. */ - ~Ptr(); - - /** - Assignment replaces the current Ptr instance with one that owns and stores same pointers as o and - then destroys the old instance. - @param o Ptr to share ownership with. - */ - Ptr& operator = (const Ptr& o); - - /** @overload */ - template - Ptr& operator = (const Ptr& o); - - /** If no other Ptr instance owns the owned pointer, deletes it with the associated deleter. Then sets - both the owned and the stored pointers to NULL. - */ - void release(); - - /** - `ptr.reset(...)` is equivalent to `ptr = Ptr(...)`. - @param p Pointer to own. - */ - template - void reset(Y* p); - - /** @overload - @param d Deleter to use for the owned pointer. - @param p Pointer to own. - */ - template - void reset(Y* p, D d); - - /** - Swaps the owned and stored pointers (and deleters, if any) of this and o. - @param o Ptr to swap with. - */ - void swap(Ptr& o); - - /** Returns the stored pointer. */ - T* get() const; - - /** Ordinary pointer emulation. */ - typename detail::RefOrVoid::type operator * () const; - - /** Ordinary pointer emulation. */ - T* operator -> () const; - - /** Equivalent to get(). */ - operator T* () const; - - /** ptr.empty() is equivalent to `!ptr.get()`. */ - bool empty() const; - - /** Returns a Ptr that owns the same pointer as this, and stores the same - pointer as this, except converted via static_cast to Y*. - */ - template - Ptr staticCast() const; - - /** Ditto for const_cast. */ - template - Ptr constCast() const; - - /** Ditto for dynamic_cast. */ - template - Ptr dynamicCast() const; - - Ptr(Ptr&& o); - Ptr& operator = (Ptr&& o); - -private: - detail::PtrOwner* owner; - T* stored; - - template - friend struct Ptr; // have to do this for the cross-type copy constructor -}; - -/** Equivalent to ptr1.swap(ptr2). Provided to help write generic algorithms. */ -template -void swap(Ptr& ptr1, Ptr& ptr2); - -/** Return whether ptr1.get() and ptr2.get() are equal and not equal, respectively. */ -template -bool operator == (const Ptr& ptr1, const Ptr& ptr2); -template -bool operator != (const Ptr& ptr1, const Ptr& ptr2); - -/** `makePtr(...)` is equivalent to `Ptr(new T(...))`. It is shorter than the latter, and it's -marginally safer than using a constructor or Ptr::reset, since it ensures that the owned pointer -is new and thus not owned by any other Ptr instance. -Unfortunately, perfect forwarding is impossible to implement in C++03, and so makePtr is limited -to constructors of T that have up to 10 arguments, none of which are non-const references. - */ -template -Ptr makePtr(); -/** @overload */ -template -Ptr makePtr(const A1& a1); -/** @overload */ -template -Ptr makePtr(const A1& a1, const A2& a2); -/** @overload */ -template -Ptr makePtr(const A1& a1, const A2& a2, const A3& a3); -/** @overload */ -template -Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4); -/** @overload */ -template -Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5); -/** @overload */ -template -Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6); -/** @overload */ -template -Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7); -/** @overload */ -template -Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8); -/** @overload */ -template -Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9); -/** @overload */ -template -Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10); - //////////////////////////////// string class //////////////////////////////// class CV_EXPORTS FileNode; //for string constructor from FileNode @@ -488,6 +187,4 @@ static inline std::string toUpperCase(const std::string& str) //! @} core_basic } // cv -#include "opencv2/core/ptr.inl.hpp" - #endif //OPENCV_CORE_CVSTD_HPP diff --git a/modules/core/include/opencv2/core/cvstd_wrapper.hpp b/modules/core/include/opencv2/core/cvstd_wrapper.hpp new file mode 100644 index 0000000000..358a47eb4b --- /dev/null +++ b/modules/core/include/opencv2/core/cvstd_wrapper.hpp @@ -0,0 +1,147 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +#ifndef OPENCV_CORE_CVSTD_WRAPPER_HPP +#define OPENCV_CORE_CVSTD_WRAPPER_HPP + +#include "opencv2/core/cvdef.h" + +#include +#include // std::shared_ptr +#include // std::enable_if + +namespace cv { + +using std::nullptr_t; + +//! @addtogroup core_basic +//! @{ + +#ifdef CV_DOXYGEN + +template using Ptr = std::shared_ptr<_Tp>; // In ideal world it should look like this, but we need some compatibility workarounds below + +template static inline +Ptr<_Tp> makePtr(const A1&... a1) { return std::make_shared<_Tp>(a1...); } + +#else // cv::Ptr with compatibility workarounds + +template +struct DefaultDeleter +{ +#ifndef _MSC_VER + void operator()(Y* p) const = delete; // not available by default; enabled for specializations only +#else + void operator()(Y* p) const { delete p; } +#endif +}; + +namespace sfinae { +template +struct has_parenthesis_operator +{ +private: + template + static constexpr std::true_type check(typename std::is_same().operator()(std::declval()...))>::type, Ret>::type*); + + template static constexpr std::false_type check(...); + + typedef decltype(check(0)) type; + +public: + static constexpr bool value = type::value; +}; +} // namespace sfinae + +template using has_custom_delete = sfinae::has_parenthesis_operator, void, Y*>; + +template +struct Ptr : public std::shared_ptr +{ +#if 0 + using std::shared_ptr::shared_ptr; // GCC 5.x can't handle this +#else + inline Ptr() noexcept : std::shared_ptr() {} + inline Ptr(nullptr_t) noexcept : std::shared_ptr(nullptr) {} + template inline Ptr(Y* p, D d) : std::shared_ptr(p, d) {} + template inline Ptr(nullptr_t, D d) : std::shared_ptr(nullptr, d) {} + + template inline Ptr(const Ptr& r, T* ptr) noexcept : std::shared_ptr(r, ptr) {} + + inline Ptr(const Ptr& o) noexcept : std::shared_ptr(o) {} + inline Ptr(Ptr&& o) noexcept : std::shared_ptr(std::move(o)) {} + + template inline Ptr(const Ptr& o) noexcept : std::shared_ptr(o) {} + template inline Ptr(Ptr&& o) noexcept : std::shared_ptr(std::move(o)) {} +#endif + inline Ptr(const std::shared_ptr& o) noexcept : std::shared_ptr(o) {} + inline Ptr(std::shared_ptr&& o) noexcept : std::shared_ptr(std::move(o)) {} + +#ifndef _MSC_VER + // Overload with custom DefaultDeleter: Ptr(...) + template::value >::type> + inline Ptr(Y* ptr) : std::shared_ptr(ptr, DefaultDeleter()) {} + + // Overload without custom deleter: Ptr(...); + template::value, int >::type) > + inline Ptr(Y* ptr) : std::shared_ptr(ptr) {} + + // Overload with custom DefaultDeleter: Ptr(...) + template::value >::type> + inline void reset(Y* ptr) { std::shared_ptr::reset(ptr, DefaultDeleter()); } + + // Overload without custom deleter: Ptr(...); + template::value, int >::type) > + inline void reset(Y* ptr) { std::shared_ptr::reset(ptr); } +#else + template + inline Ptr(Y* ptr) : std::shared_ptr(ptr, DefaultDeleter()) {} + + template + inline void reset(Y* ptr) { std::shared_ptr::reset(ptr, DefaultDeleter()); } +#endif + + template + void reset(Y* ptr, Deleter d) { std::shared_ptr::reset(ptr, d); } + + void reset() noexcept { std::shared_ptr::reset(); } + + Ptr& operator=(const Ptr& o) { std::shared_ptr::operator =(o); return *this; } + template inline Ptr& operator=(const Ptr& o) { std::shared_ptr::operator =(o); return *this; } + + T* operator->() const noexcept { return std::shared_ptr::get();} + typename std::add_lvalue_reference::type operator*() const noexcept { return *std::shared_ptr::get(); } + + // OpenCV 3.x methods (not a part of standart C++ library) + inline void release() { std::shared_ptr::reset(); } + inline operator T* () const { return std::shared_ptr::get(); } + inline bool empty() const { return std::shared_ptr::get() == NULL; } + + template inline + Ptr staticCast() const noexcept { return std::static_pointer_cast(*this); } + + template inline + Ptr constCast() const noexcept { return std::const_pointer_cast(*this); } + + template inline + Ptr dynamicCast() const noexcept { return std::dynamic_pointer_cast(*this); } +}; + +template static inline +Ptr<_Tp> makePtr(const A1&... a1) +{ +#ifndef _MSC_VER + static_assert( !has_custom_delete<_Tp>::value, "Can't use this makePtr with custom DefaultDeleter"); + return (Ptr<_Tp>)std::make_shared<_Tp>(a1...); +#else + return Ptr<_Tp>(new _Tp(a1...), DefaultDeleter<_Tp>()); +#endif +} + +#endif // CV_DOXYGEN + +//! @} core_basic +} // cv + +#endif //OPENCV_CORE_CVSTD_WRAPPER_HPP diff --git a/modules/core/include/opencv2/core/ptr.inl.hpp b/modules/core/include/opencv2/core/ptr.inl.hpp deleted file mode 100644 index 9165de0993..0000000000 --- a/modules/core/include/opencv2/core/ptr.inl.hpp +++ /dev/null @@ -1,375 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2013, NVIDIA Corporation, all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the copyright holders or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ - -#ifndef OPENCV_CORE_PTR_INL_HPP -#define OPENCV_CORE_PTR_INL_HPP - -#include - -//! @cond IGNORED - -namespace cv { - -template -void DefaultDeleter::operator () (Y* p) const -{ - delete p; -} - -namespace detail -{ - -struct PtrOwner -{ - PtrOwner() : refCount(1) - {} - - void incRef() - { - CV_XADD(&refCount, 1); - } - - void decRef() - { - if (CV_XADD(&refCount, -1) == 1) deleteSelf(); - } - -protected: - /* This doesn't really need to be virtual, since PtrOwner is never deleted - directly, but it doesn't hurt and it helps avoid warnings. */ - virtual ~PtrOwner() - {} - - virtual void deleteSelf() = 0; - -private: - unsigned int refCount; - - // noncopyable - PtrOwner(const PtrOwner&); - PtrOwner& operator = (const PtrOwner&); -}; - -template -struct PtrOwnerImpl CV_FINAL : PtrOwner -{ - PtrOwnerImpl(Y* p, D d) : owned(p), deleter(d) - {} - - void deleteSelf() CV_OVERRIDE - { - deleter(owned); - delete this; - } - -private: - Y* owned; - D deleter; -}; - - -} - -template -Ptr::Ptr() : owner(NULL), stored(NULL) -{} - -template -template -Ptr::Ptr(Y* p) - : owner(p - ? new detail::PtrOwnerImpl >(p, DefaultDeleter()) - : NULL), - stored(p) -{} - -template -template -Ptr::Ptr(Y* p, D d) - : owner(p - ? new detail::PtrOwnerImpl(p, d) - : NULL), - stored(p) -{} - -template -Ptr::Ptr(const Ptr& o) : owner(o.owner), stored(o.stored) -{ - if (owner) owner->incRef(); -} - -template -template -Ptr::Ptr(const Ptr& o) : owner(o.owner), stored(o.stored) -{ - if (owner) owner->incRef(); -} - -template -template -Ptr::Ptr(const Ptr& o, T* p) : owner(o.owner), stored(p) -{ - if (owner) owner->incRef(); -} - -template -Ptr::~Ptr() -{ - release(); -} - -template -Ptr& Ptr::operator = (const Ptr& o) -{ - Ptr(o).swap(*this); - return *this; -} - -template -template -Ptr& Ptr::operator = (const Ptr& o) -{ - Ptr(o).swap(*this); - return *this; -} - -template -void Ptr::release() -{ - if (owner) owner->decRef(); - owner = NULL; - stored = NULL; -} - -template -template -void Ptr::reset(Y* p) -{ - Ptr(p).swap(*this); -} - -template -template -void Ptr::reset(Y* p, D d) -{ - Ptr(p, d).swap(*this); -} - -template -void Ptr::swap(Ptr& o) -{ - std::swap(owner, o.owner); - std::swap(stored, o.stored); -} - -template -T* Ptr::get() const -{ - return stored; -} - -template -typename detail::RefOrVoid::type Ptr::operator * () const -{ - return *stored; -} - -template -T* Ptr::operator -> () const -{ - return stored; -} - -template -Ptr::operator T* () const -{ - return stored; -} - - -template -bool Ptr::empty() const -{ - return !stored; -} - -template -template -Ptr Ptr::staticCast() const -{ - return Ptr(*this, static_cast(stored)); -} - -template -template -Ptr Ptr::constCast() const -{ - return Ptr(*this, const_cast(stored)); -} - -template -template -Ptr Ptr::dynamicCast() const -{ - return Ptr(*this, dynamic_cast(stored)); -} - -template -Ptr::Ptr(Ptr&& o) : owner(o.owner), stored(o.stored) -{ - o.owner = NULL; - o.stored = NULL; -} - -template -Ptr& Ptr::operator = (Ptr&& o) -{ - if (this == &o) - return *this; - - release(); - owner = o.owner; - stored = o.stored; - o.owner = NULL; - o.stored = NULL; - return *this; -} - - -template -void swap(Ptr& ptr1, Ptr& ptr2){ - ptr1.swap(ptr2); -} - -template -bool operator == (const Ptr& ptr1, const Ptr& ptr2) -{ - return ptr1.get() == ptr2.get(); -} - -template -bool operator != (const Ptr& ptr1, const Ptr& ptr2) -{ - return ptr1.get() != ptr2.get(); -} - -template -Ptr makePtr() -{ - return Ptr(new T()); -} - -template -Ptr makePtr(const A1& a1) -{ - return Ptr(new T(a1)); -} - -template -Ptr makePtr(const A1& a1, const A2& a2) -{ - return Ptr(new T(a1, a2)); -} - -template -Ptr makePtr(const A1& a1, const A2& a2, const A3& a3) -{ - return Ptr(new T(a1, a2, a3)); -} - -template -Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4) -{ - return Ptr(new T(a1, a2, a3, a4)); -} - -template -Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) -{ - return Ptr(new T(a1, a2, a3, a4, a5)); -} - -template -Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) -{ - return Ptr(new T(a1, a2, a3, a4, a5, a6)); -} - -template -Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) -{ - return Ptr(new T(a1, a2, a3, a4, a5, a6, a7)); -} - -template -Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) -{ - return Ptr(new T(a1, a2, a3, a4, a5, a6, a7, a8)); -} - -template -Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9) -{ - return Ptr(new T(a1, a2, a3, a4, a5, a6, a7, a8, a9)); -} - -template -Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10) -{ - return Ptr(new T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)); -} - -template -Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10, const A11& a11) -{ - return Ptr(new T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11)); -} - -template -Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10, const A11& a11, const A12& a12) -{ - return Ptr(new T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)); -} -} // namespace cv - -//! @endcond - -#endif // OPENCV_CORE_PTR_INL_HPP From 64b3c1e6915d14b3a66f584c6f229139da5e321e Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 7 Sep 2018 22:16:53 +0000 Subject: [PATCH 2/3] core(test): update cv::Ptr tests --- modules/core/test/test_ptr.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/modules/core/test/test_ptr.cpp b/modules/core/test/test_ptr.cpp index 2a099846a8..24d947c36d 100644 --- a/modules/core/test/test_ptr.cpp +++ b/modules/core/test/test_ptr.cpp @@ -98,22 +98,25 @@ TEST(Core_Ptr, owning_ctor) Ptr p(r); EXPECT_EQ(r, p.get()); } - EXPECT_TRUE(deleted); { Ptr p(&dummyObject, ReportingDeleter(&deleted)); EXPECT_EQ(&dummyObject, p.get()); } - EXPECT_TRUE(deleted); { Ptr p((void*)0, ReportingDeleter(&deleted)); EXPECT_NULL(p.get()); } + EXPECT_TRUE(deleted); // Differ from OpenCV 3.4 (but conformant to std::shared_ptr, see below) - EXPECT_FALSE(deleted); + { + std::shared_ptr p((void*)0, ReportingDeleter(&deleted)); + EXPECT_NULL(p.get()); + } + EXPECT_TRUE(deleted); } TEST(Core_Ptr, sharing_ctor) @@ -337,7 +340,7 @@ TEST(Core_Ptr, casts) Ptr p2 = p1.dynamicCast(); EXPECT_NULL(p2.get()); p1.release(); - EXPECT_FALSE(deleted); + EXPECT_TRUE(deleted); } EXPECT_TRUE(deleted); @@ -400,4 +403,16 @@ TEST(Core_Ptr, specialized_deleter) ASSERT_TRUE(sd.deleted); } +TEST(Core_Ptr, specialized_deleter_via_reset) +{ + SpeciallyDeletable sd; + + { + Ptr p; + p.reset(&sd); + } + + ASSERT_TRUE(sd.deleted); +} + }} // namespace From df8b057b443c9feecc22b32141363ae7d1838030 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Sat, 8 Sep 2018 16:49:11 +0000 Subject: [PATCH 3/3] avoid `Ptr<> == NULL` checks --- modules/core/src/lut.cpp | 17 +++++------------ modules/core/src/persistence_cpp.cpp | 2 +- modules/core/test/test_io.cpp | 6 +++--- .../src/ocl4dnn/src/ocl4dnn_conv_spatial.cpp | 2 +- modules/ml/test/test_mltests2.cpp | 4 ++-- samples/cpp/detect_blob.cpp | 2 +- samples/cpp/detect_mser.cpp | 2 +- 7 files changed, 14 insertions(+), 21 deletions(-) diff --git a/modules/core/src/lut.cpp b/modules/core/src/lut.cpp index 3e91bd9fcb..8f3381be4d 100644 --- a/modules/core/src/lut.cpp +++ b/modules/core/src/lut.cpp @@ -384,21 +384,14 @@ void cv::LUT( InputArray _src, InputArray _lut, OutputArray _dst ) if (_src.dims() <= 2) { bool ok = false; - Ptr body; - - if (body == NULL || ok == false) - { - ok = false; - ParallelLoopBody* p = new LUTParallelBody(src, lut, dst, &ok); - body.reset(p); - } - if (body != NULL && ok) + LUTParallelBody body(src, lut, dst, &ok); + if (ok) { Range all(0, dst.rows); - if (dst.total()>>18) - parallel_for_(all, *body, (double)std::max((size_t)1, dst.total()>>16)); + if (dst.total() >= (size_t)(1<<18)) + parallel_for_(all, body, (double)std::max((size_t)1, dst.total()>>16)); else - (*body)(all); + body(all); if (ok) return; } diff --git a/modules/core/src/persistence_cpp.cpp b/modules/core/src/persistence_cpp.cpp index 7e4ae71946..bcdee94f60 100644 --- a/modules/core/src/persistence_cpp.cpp +++ b/modules/core/src/persistence_cpp.cpp @@ -537,7 +537,7 @@ void read( const FileNode& node, SparseMat& mat, const SparseMat& default_mat ) return; } Ptr m((CvSparseMat*)cvRead((CvFileStorage*)node.fs, (CvFileNode*)*node)); - CV_Assert(CV_IS_SPARSE_MAT(m)); + CV_Assert(CV_IS_SPARSE_MAT(m.get())); m->copyToSparseMat(mat); } diff --git a/modules/core/test/test_io.cpp b/modules/core/test/test_io.cpp index c7473b9ded..33583b4d1b 100644 --- a/modules/core/test/test_io.cpp +++ b/modules/core/test/test_io.cpp @@ -288,9 +288,9 @@ protected: fs["test_sparse_mat"] >> m_s2; Ptr _m_s2(cvCreateSparseMat(m_s2)); - if( !m_s || !CV_IS_SPARSE_MAT(m_s) || - !cvTsCheckSparse(m_s, _test_sparse, 0) || - !cvTsCheckSparse(_m_s2, _test_sparse, 0)) + if( !m_s || !CV_IS_SPARSE_MAT(m_s.get()) || + !cvTsCheckSparse(m_s.get(), _test_sparse.get(), 0) || + !cvTsCheckSparse(_m_s2.get(), _test_sparse.get(), 0)) { ts->printf( cvtest::TS::LOG, "the read sparse matrix is not correct\n" ); ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); diff --git a/modules/dnn/src/ocl4dnn/src/ocl4dnn_conv_spatial.cpp b/modules/dnn/src/ocl4dnn/src/ocl4dnn_conv_spatial.cpp index a3a0936bd4..68e89d5694 100644 --- a/modules/dnn/src/ocl4dnn/src/ocl4dnn_conv_spatial.cpp +++ b/modules/dnn/src/ocl4dnn/src/ocl4dnn_conv_spatial.cpp @@ -1820,7 +1820,7 @@ void OCL4DNNConvSpatial::prepareKernel(const UMat &bottom, UMat &top, std::string previous_key = key_; generateKey(); - if (key_.compare(previous_key) == 0 && bestKernelConfig != NULL) + if (key_.compare(previous_key) == 0 && bestKernelConfig) return; if (bestKernelConfig) diff --git a/modules/ml/test/test_mltests2.cpp b/modules/ml/test/test_mltests2.cpp index 1b1c21cfeb..44d5aeb992 100644 --- a/modules/ml/test/test_mltests2.cpp +++ b/modules/ml/test/test_mltests2.cpp @@ -237,7 +237,7 @@ TEST(ML_ANN, ActivationFunction) x->save(dataname + activationName[i] + ".yml"); #else Ptr y = Algorithm::load(dataname + activationName[i] + ".yml"); - ASSERT_TRUE(y != NULL) << "Could not load " << dataname + activationName[i] + ".yml"; + ASSERT_TRUE(y) << "Could not load " << dataname + activationName[i] + ".yml"; Mat testSamples = tdata->getTestSamples(); Mat rx, ry, dst; x->predict(testSamples, rx); @@ -330,7 +330,7 @@ TEST_P(ML_ANN_METHOD, Test) #endif ASSERT_FALSE(r_gold.empty()); Ptr y = Algorithm::load(filename); - ASSERT_TRUE(y != NULL) << "Could not load " << filename; + ASSERT_TRUE(y) << "Could not load " << filename; Mat rx, ry; for (int j = 0; j < 4; j++) { diff --git a/samples/cpp/detect_blob.cpp b/samples/cpp/detect_blob.cpp index 3acb8fa1fb..db86a07ee2 100644 --- a/samples/cpp/detect_blob.cpp +++ b/samples/cpp/detect_blob.cpp @@ -178,7 +178,7 @@ int main(int argc, char *argv[]) vector zone; vector > region; Mat desc, result(img.rows, img.cols, CV_8UC3); - if (b.dynamicCast() != NULL) + if (b.dynamicCast().get()) { Ptr sbd = b.dynamicCast(); sbd->detect(img, keyImg, Mat()); diff --git a/samples/cpp/detect_mser.cpp b/samples/cpp/detect_mser.cpp index 8d62b2b7e4..7c2833fea4 100644 --- a/samples/cpp/detect_mser.cpp +++ b/samples/cpp/detect_mser.cpp @@ -500,7 +500,7 @@ int main(int argc, char *argv[]) vector > region; Mat desc; - if (b.dynamicCast() != NULL) + if (b.dynamicCast().get()) { Ptr sbd = b.dynamicCast(); sbd->detectRegions(img, region, zone);