How to fix discards qualifiers [-fpermissive] for cv::SVMParams? - c++

I have a class ConfigFile that has a getter for the SVMParams member:
cv::SVMParams gerSVMParams()
{
return *m_mapConfig["SVMParams"];
}
The code is a little bit more complicated. m_mapConfig is a
std::map<std::string, std::unique_ptr< IConfigItem > >
And IConfigItem is a template class that looks like this for SVMParams:
template<> class ConfigItem< cv::SVMParams > : public IConfigItem
{
private:
cv::SVMParams m_value;
public:
ConfigItem(const cv::SVMParams& valueIn) : m_value(valueIn) {}
operator cv::SVMParams() const
{
return m_value;
}
};
My problem is when I am trying to auto train the SVM classifier:
classifier.train_auto(trainingData, classes, cv::Mat(), cv::Mat(), configFileIn.getSVMParams());
I am getting an error of kind:
error: passing ‘const ConfigFile’ as ‘this’ argument of ‘cv::SVMParams ConfigFile::getSVMParams()’ discards qualifiers [-fpermissive]
Any suggestions of what I am doing wrong? Or is there a small bug because because the train_auto functions has no const in front of the SVMParams parameter. Or is it modifying it?

Make your function const:
cv::SVMParams gerSVMParams() const
// ^^^^^
The error is you are calling a non-const method on a const object, which the compiler rejects as being potentially unsafe. That said, your implementation is inherently non-const too since you might be inserting an object into your map, so just adding the const won't help.
What you probably want to do is:
cv::SVMParams gerSVMParams() const
// ^^^^^
{
auto it = m_mapConfig.find("SVMParams");
if (it != m_mapConfig.end()) {
return *(*it);
}
else {
return {}; // maybe?
}
}

Found the problem: I was calling the function in which I was calling the getSVMParams() with const ConfigFile&; and that was not allowed by the shared_ptr I used in the map.
Thanks all, anyway!

Related

Passing ‘const ...’ as ‘this’ argument discards qualifiers

I'm stuck. When trying to add a new element to the vector of strings inside a struct via the iterator I get this error about const qualifier:
error: passing ‘const std::vector<std::__cxx11::basic_string<char> >’ as ‘this’ argument discards qualifiers [-fpermissive]
175 | p->children.push_back("New child");
The code:
typedef struct Concept_tree
{
string id;
string name;
std::vector<string> children;
bool operator==(const Concept_tree &ct2)
{
return (id == ct2.id);
}
Concept_tree() { };
Concept_tree(string id): id(id) { };
Concept_tree(string id, string term): id(id), name(term) { };
}
Concept_tree;
namespace std
{
template<>
struct hash<Concept_tree>
{
size_t operator()(const Concept_tree &ct) const
{
return std::hash<string>()(ct.id);
}
};
}
...
std::unordered_set<Concept_tree> ct_uset;
...
string test = "id00001";
auto p = ct_uset.find(test);
p->children.push_back("New child");
I understand the cause of the error but can't deduce its exact position. Is it that the constructors are implemented improperly? Could anyone help?
You got the iterator p from an unordered_set; the contents of unordered_set are immutable (to avoid violating invariants), and the iterator returned is a const view of the elements to ensure that.
You could mark children as mutable so it can be mutated even when the Concept_tree is const (since it's not part of equality/hash computation, this might be okay). But this will make it possible to mutate children even when you want a Concept_tree to be logically const. To avoid that, you could use an unordered_map mapping just the id (immutable key) to the actual Concept_tree (mutable value) object.
Side-note: You probably want to mark your operator== as const so this is const, or make it a non-member function with both argument const per What are the basic rules and idioms for operator overloading?.

How do I interpret this application of the safe bool idiom? [duplicate]

I was pointed to the 'safe bool idiom', and after trying to decipher what is going on (the explanation supplied on the site was not sufficient enough to grant me understanding of why it works), I decided to try to take the following code apart and make an attempt at simplifying it as much as possible. The site supplied code below:
class Testable {
bool ok_;
typedef void (Testable::*bool_type)() const;
void this_type_does_not_support_comparisons() const {}
public:
explicit Testable(bool b=true):ok_(b) {}
operator bool_type() const {
return ok_==true ?
&Testable::this_type_does_not_support_comparisons : 0;
}
};
I decided to analyse the key basis of 'bool_type' given this seems to be what it's centred on. Given the following line:
typedef void (Testable::*bool_type)() const;
One can (not so easily, due to bracketing) deduce it's a typedef of a type of 'void Testable::*', of which bool_type represents. This can be further demonstrated by making the following modifications and function calls:
class Testable {
bool ok_;
typedef void (Testable::*bool_type)() const;
void this_type_does_not_support_comparisons() const {}
public:
explicit Testable(bool b=true):ok_(b) {}
bool_type Test; //Added this
operator bool_type() const {
return ok_==true ?
&Testable::this_type_does_not_support_comparisons : 0;
}
};
int main()
{
Testable Test;
int A = Test.Test; //Compiler will give a conversion error, telling us what type .Test is in the process
}
It allows us to see what type bool_type is:
error: cannot convert 'void (Testable::*)()const' to 'int' in initialization
Which shows it is indeed a type of 'void (Testable::*)'.
The issues crops up here:
If we modify the following function:
operator bool_type() const {
return ok_==true ?
&Testable::this_type_does_not_support_comparisons : 0;
}
And turn it into:
operator void Testable::* () const //Same as bool_type, right?
{
return ok_==true ?
&Testable::this_type_does_not_support_comparisons : 0;
}
It generates the following complaints:
error: expected identifier before '*' token
error: '< invalid operator >' declared as function returning a function
My questions are thus:
Why is it generating those complaints if 'void (Testable::*) is indeed the typedef for bool_type?
And
What is going on here?
Your reasoning goes wrong about here
operator void Testable::* () const //Same as bool_type, right?
This isn't correct. The type of bool_type is, as the compiler tells us in the error message:
'void (Testable::*)()const'
So, to replace it in the operator, you would need something like
operator (void (Testable::*)() const) () const
if that is ever possible! See why even the ugly typedef is an improvement?
In C++11 we also have the new construct explicit operator bool() to save us from this ugliness.

Wrapping a unique_ptr with custom class in a container

I took my first C++ class in 1990, long before your newfangled exceptions, STL and whatnot. Now I am writing a custom C++ container and I decided I would use this as an opportunity to learn some C++11 techniques and concepts, especially unique_ptr. Unfortunately I am having some trouble with the move semantics (I think) when inserting an element. Here is a very stripped down version of the code I am trying to get to compile:
#include <vector>
#include <memory>
struct Key {
int k_;
Key() : k_(0){};
explicit Key(int k) : k_(k){};
Key(const Key &o) : k_(o.k_) {}
Key(Key &&o) { k_ = std::move(o.k_); }
Key &operator=(const Key &o) {
k_ = o.k_;
return *this;
}
Key &operator=(Key &&o) {
k_ = std::move(o.k_);
return *this;
}
int get() const { return k_; }
};
template <class T> class CustomContainer {
public:
typedef std::pair<Key, std::unique_ptr<Key>> Record;
CustomContainer() {}
~CustomContainer(){};
bool insert(const Record &record) {
objects.emplace_back(std::move(record));
return true;
}
std::vector<Record> objects;
};
int main() {
CustomContainer<Key> q;
q.insert(CustomContainer<Key>::Record(Key(1), std::unique_ptr<Key>(new Key(1))));
}
I am inserting a pointer to a Key object to keep the code simple. In my actual application, Key is a little more complicated, T is not Key, and the Custom container has many more member functions, but this is enough to highlight the problem. When I just have a unique_ptr object in the vector, everything appears to work just fine. As soon as I add the pair, I get:
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/ext/new_allocator.h:120:23: error: call to
implicitly-deleted copy constructor of 'std::pair<Key, std::unique_ptr<Key, std::default_delete<Key> > >'
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
.
.
.
simple.cc:33:13: note: in instantiation of function template specialization 'std::vector<std::pair<Key,
std::unique_ptr<Key, std::default_delete<Key> > >, std::allocator<std::pair<Key, std::unique_ptr<Key,
std::default_delete<Key> > > > >::emplace_back<const std::pair<Key, std::unique_ptr<Key,
std::default_delete<Key> > > >' requested here
objects.emplace_back(std::move(record));
^
simple.cc:41:5: note: in instantiation of member function 'CustomContainer<Key>::insert' requested here
q.insert(CustomContainer<Key>::Record(Key(1), std::unique_ptr<Key>(new Key(1))));
I tried the same thing with a custom class instead of a pair and got the same error. I can't seem to get the compiler to call the move constructor instead of the copy constructor no matter how many std::move()s I add. What am I missing?
you're passing a const ref to a unique_ptr and then trying to copy from it (you can only move from a non-const). Pass the entire object and then move from that. Since you're initialising with a temporary (r-value reference), there will be an implicit move at the call site.
patch to fix your code is here:
template <class T> class CustomContainer {
public:
...
bool insert(Record record) { // <-- FIXED
...
}
};

Using an iterator template class as a parameter to a function

return Graph_iterator_Vertex(Vertexs.begin());
I do not understand why this line is called the copy constructor, although there is my constructor with a parameter. The arguments constructor parameter written specifically for this design.
All that I have found about a similar issue is the use of typename. But it did not solve my problem.
struct Graph_iterator_Vertex
{
private:
typename std::vector<Vertex<Type_Of_Value_Vertex, Type_Of_Value_Edge>>::iterator iterator;
public:
Graph_iterator_Vertex(typename std::_Vector_const_iterator<std::vector<Vertex<Type_Of_Value_Vertex, Type_Of_Value_Edge>>> iterator_)
{
iterator=iterator_
}
};
const Graph_iterator_Vertex begin(void) const
{
return Graph_iterator_Vertex(Vertexs.begin());
}
where
std::vector<Vertex<Type_Of_Value_Vertex, Type_Of_Value_Edge>> Vertexs;
Error:
error C2440: <function-style-cast>: can not be converted std::_Vector_const_iterator<_Myvec>"in "Graph<Type_Of_Value_Vertex,Type_Of_Value_Edge>::Graph_iterator_Vertex"
you should use
std::vector<Vertex<Type_Of_Value_Vertex, Type_Of_Value_Edge>>::const_iterator
instead of
std::_Vector_const_iterator<std::vector<Vertex<Type_Of_Value_Vertex, Type_Of_Value_Edge>>>
as the type of your function parameter.

How does the safe bool idiom bool_type (and the safe bool idiom) work?

I was pointed to the 'safe bool idiom', and after trying to decipher what is going on (the explanation supplied on the site was not sufficient enough to grant me understanding of why it works), I decided to try to take the following code apart and make an attempt at simplifying it as much as possible. The site supplied code below:
class Testable {
bool ok_;
typedef void (Testable::*bool_type)() const;
void this_type_does_not_support_comparisons() const {}
public:
explicit Testable(bool b=true):ok_(b) {}
operator bool_type() const {
return ok_==true ?
&Testable::this_type_does_not_support_comparisons : 0;
}
};
I decided to analyse the key basis of 'bool_type' given this seems to be what it's centred on. Given the following line:
typedef void (Testable::*bool_type)() const;
One can (not so easily, due to bracketing) deduce it's a typedef of a type of 'void Testable::*', of which bool_type represents. This can be further demonstrated by making the following modifications and function calls:
class Testable {
bool ok_;
typedef void (Testable::*bool_type)() const;
void this_type_does_not_support_comparisons() const {}
public:
explicit Testable(bool b=true):ok_(b) {}
bool_type Test; //Added this
operator bool_type() const {
return ok_==true ?
&Testable::this_type_does_not_support_comparisons : 0;
}
};
int main()
{
Testable Test;
int A = Test.Test; //Compiler will give a conversion error, telling us what type .Test is in the process
}
It allows us to see what type bool_type is:
error: cannot convert 'void (Testable::*)()const' to 'int' in initialization
Which shows it is indeed a type of 'void (Testable::*)'.
The issues crops up here:
If we modify the following function:
operator bool_type() const {
return ok_==true ?
&Testable::this_type_does_not_support_comparisons : 0;
}
And turn it into:
operator void Testable::* () const //Same as bool_type, right?
{
return ok_==true ?
&Testable::this_type_does_not_support_comparisons : 0;
}
It generates the following complaints:
error: expected identifier before '*' token
error: '< invalid operator >' declared as function returning a function
My questions are thus:
Why is it generating those complaints if 'void (Testable::*) is indeed the typedef for bool_type?
And
What is going on here?
Your reasoning goes wrong about here
operator void Testable::* () const //Same as bool_type, right?
This isn't correct. The type of bool_type is, as the compiler tells us in the error message:
'void (Testable::*)()const'
So, to replace it in the operator, you would need something like
operator (void (Testable::*)() const) () const
if that is ever possible! See why even the ugly typedef is an improvement?
In C++11 we also have the new construct explicit operator bool() to save us from this ugliness.