In a nutshell, I need help with the right use of unique_ptr
and not with the library ArmNN
. So, the next paragraph is just for contextualization.
I am adapting my current application to use the library ArmNN. More specifically, I am doing that through the use of the interface ICaffeParser.
At line 22 of this interface, we have this using
definition to define a unique_ptr
to the interface, that I believe is the "cause" of my problems.
using ICaffeParserPtr = std::unique_ptr<ICaffeParser, void(*)(ICaffeParser* parser)>;
I am quite sure my problem is the incorrect use of unique_ptr
in my context, once I could make some successful tests with a more simple application.
My current code contains a class, let's call it MyClass
:
namespace MYNAMESPACE {
class MyClass {
public:
MyClass() {
}
// a lot of functions
// a lot of attributes
private:
// a lot of functions
// a lot of attributes
}
}
In order to make use of the ArmNN
library, I have created a new private
attribute for MyClass
:
armnnCaffeParser::ICaffeParserPtr myParser;
and instantiated myParser
at MyClass()
constructor:
MyClass::MyClass() {
myParser = armnnCaffeParser::ICaffeParser::Create();
}
Remembering ICaffeParserPtr
is a unique_ptr
(I think), now I have the following compiling error:
/my_path/src/detector.cpp: In constructor ‘MYNAMESPACE::MyClass::MyClass()’:
/my_path/src/detector.cpp:13:20: error: no matching function for call to ‘std::unique_ptr<armnnCaffeParser::ICaffeParser, void (*)(armnnCaffeParser::ICaffeParser*)>::unique_ptr()’
MyClass::MyClass() {
^
In file included from /usr/aarch64-linux-gnu/include/c++/7/bits/locale_conv.h:41:0,
from /usr/aarch64-linux-gnu/include/c++/7/locale:43,
from /usr/aarch64-linux-gnu/include/c++/7/iomanip:43,
from /usr/include/opencv2/flann/lsh_table.h:40,
from /usr/include/opencv2/flann/lsh_index.h:49,
from /usr/include/opencv2/flann/all_indices.h:42,
from /usr/include/opencv2/flann/flann_base.hpp:43,
from /usr/include/opencv2/flann.hpp:48,
from /usr/include/opencv2/opencv.hpp:62,
from /my_path/src/detector.hpp:11,
from /my_path/src/detector.cpp:1:
/usr/aarch64-linux-gnu/include/c++/7/bits/unique_ptr.h:255:2: note: candidate: template<class _Up, class> std::unique_ptr<_Tp, _Dp>::unique_ptr(std::auto_ptr<_Up>&&)
unique_ptr(auto_ptr<_Up>&& __u) noexcept;
/usr/aarch64-linux-gnu/include/c++/7/bits/unique_ptr.h:255:2: note: template argument deduction/substitution failed:
/my_path/src/detector.cpp:13:20: note: candidate expects 1 argument, 0 provided
MyClass::MyClass() {
^
The error happens because myParser
is actually being default-initialized and then assigned on the constructor body of MyClass::MyClass()
.
Since a function pointer is passed as a custom deleter to std::unique_ptr
to form the ICaffeParserPtr
type, the default constructor for this particular instance of std::unique_ptr
is disabled as per [unique.ptr.single.ctor].
In other words, ICaffeParserPtr
, for safety reasons, cannot be default-initialized — which specific function to otherwise assign as its deleter on initialization?
To address this, you should always initialize class members at the member initializer list. In this case, initialize myParser
as such:
MyClass::MyClass():
myParser(armnnCaffeParser::ICaffeParser::Create()) {}
This avoids calling the unavailable default constructor for std::unique_ptr
, and is generally a better practice than assigning to class members in the constructor body.