I can't understand why i can see still that comunication from compilator , i have used const vector and also my pointer which i declared it's also a const , some sugestions ?
base.cpp
void CBase::setSensor(const CSensor *pSensor) const
{
if(table.size() < size_of_table)
{
table.push_back(pSensor) ;
}
else
throw CException("Przekroczono rozmiar tablicy , pozostale sensory nie zostaly dodane");
}
base.h
vector <const CSensor *> table;
I tried to use diffrent combination of const but still nothing.
Related
I have a Container class that is meant to store a vector of shared pointers. Whenever an item is appended to the Container, I want it to assume ownership of that item. In other words, when the Container is deconstructed, all of the elements inside it should also be deconstructed.
template <typename T>
class Container
{
private:
const std::vector<std::shared_ptr<T>> vec_;
public:
void append(std::shared_ptr<T> item)
{
vec_.push_back(std::move(item));
}
void printElements()
{
for (int i = 0; i < vec_.size(); i++) { std::cout << vec_[i] << std::endl; }
}
};
int main(int argc, char** argv) {
std::unique_ptr<Container<std::string>> c = std::make_unique<Container<std::string>>();
c->append(std::make_shared<std::string>("hello"));
return 0;
}
The problem is, I get the following error on vec_.push_back(std::move(item)).
No matching member function for call to 'push_back'
I'm not sure why this error is occurring.
Original answer:
Your std::vector, vec_ is const. Seems to me that would forcefully remove or disable any method, such as push_back(), which tries to modify the const vector.
Additions added 10 May 2020:
I think it's worth expounding upon this comment from #Carpetfizz in the comments under his question, too:
#GabrielStaples thanks, removing const did the trick. I thought const only protected against reassignment of vector_ but allowed for it to be mutated?
My response:
No, const here applies to the contents of the vector. The vector isn't a pointer, but what you're talking about could be done with pointers, by making the pointer itself const instead of the contents of what it points to const. Also, const and mutable are opposites. One undoes the other. You cannot have both in effect at the same time. By definition, something constant is immutable (unchangeable), and something mutable is non-constant.
And how might one make a pointer const but not the contents of what it points to?
First, consider the original code (with some minor modifications/fixes I did to it):
Run it yourself online here: https://onlinegdb.com/SyMqoeU9L
1) cpp_template_const_vector_of_smart_ptrs_test_BEFORE.cpp:
#include <iostream>
#include <memory>
#include <vector>
template <typename T>
class Container
{
private:
// const std::vector<std::shared_ptr<T>> vec_; // does NOT work
std::vector<std::shared_ptr<T>> vec_; // works!
public:
void append(std::shared_ptr<T> item)
{
vec_.push_back(std::move(item));
}
void printElements()
{
for (int i = 0; i < vec_.size(); i++)
{
// Don't forget to dereference the pointer with `*` in order to
// obtain the _contens of the pointer_ (ie: what it points to),
// rather than the pointer (address) itself
std::cout << *vec_[i] << std::endl;
}
}
};
int main(int argc, char** argv)
{
std::unique_ptr<Container<std::string>> c = std::make_unique<Container<std::string>>();
c->append(std::make_shared<std::string>("hello"));
c->append(std::make_shared<std::string>("world"));
c->printElements();
return 0;
}
Output:
hello
world
And here's the new code demonstrating how to make a constant pointer to a non-const vector. See my comments here, and study the changes:
Run it yourself online here: https://onlinegdb.com/HyjNx-L5U
2) cpp_template_const_vector_of_smart_ptrs_test_AFTER.cpp
#include <iostream>
#include <memory>
#include <vector>
template <typename T>
class Container
{
private:
// const std::vector<std::shared_ptr<T>> vec_; // does NOT work
// Create an alias to this type just to make the creation below less
// redundant in typing out the long type
using vec_type = std::vector<std::shared_ptr<T>>;
// NON-const object (vector)--so it can be changed
vec_type vec_;
// const pointer to NON-const object--so, vec_p_ can NOT be re-assigned to
// point to a new vector, because it is `const`! But, **what it points to**
// CAN be changed because it is NOT const!
vec_type * const vec_p_ = &vec_;
// This also does NOT work (in place of the line above) because it makes
// the **contents of what you're pointing to const**, which means again
// that the contents of the vector can NOT be modified.
// const vec_type * const vec_p_ = &vec_; // does NOT work
// Here's the compile-time error in gcc when compiling for C++17:
// main.cpp: In instantiation of ‘void Container<T>::append(std::shared_ptr<_Tp>) [with T = std::basic_string<char>]’:
// <span class="error_line" onclick="ide.gotoLine('main.cpp',78)">main.cpp:78:53</span>: required from here
// main.cpp:61:9: error: passing ‘const vec_type {aka const std::vector >, std::allocator > > >}’ as ‘this’ argument discards qualifiers [-fpermissive]
// vec_p_->push_back(std::move(item));
// ^~~~~~
// In file included from /usr/include/c++/7/vector:64:0,
// from main.cpp:22:
// /usr/include/c++/7/bits/stl_vector.h:953:7: note: in call to ‘void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = std::shared_ptr >; _Alloc = std::allocator > >; std::vector<_Tp, _Alloc>::value_type = std::shared_ptr >]’
// push_back(value_type&& __x)
// ^~~~~~~~~
// To prove that vec_p_ can NOT be re-assigned to point to a new vector,
// watch this:
vec_type vec2_;
// vec_p_ = &vec2_; // COMPILE-TIME ERROR! Here is the error:
// main.cpp:44:5: error: ‘vec_p_’ does not name a type; did you mean ‘vec_type’?
// vec_p_ = &vec2_; // COMPILE-TIME ERROR!
// ^~~~~~
// vec_type
// BUT, this works just fine:
vec_type * vec_p2_ = &vec2_; // non-const pointer to non-const data
public:
void append(std::shared_ptr<T> item)
{
vec_p_->push_back(std::move(item));
}
void printElements()
{
for (int i = 0; i < vec_p_->size(); i++)
{
// Notice we have to use a double de-reference here now!
std::cout << *(*vec_p_)[i] << std::endl;
}
}
};
int main(int argc, char** argv)
{
std::unique_ptr<Container<std::string>> c = std::make_unique<Container<std::string>>();
c->append(std::make_shared<std::string>("hello"));
c->append(std::make_shared<std::string>("world"));
c->printElements();
return 0;
}
Output:
hello
world
I am trying to get a constant reference back by a method for the mapped value of an unordered_map. The unordered_map is a class member. However, the code below does not work and raises the error stated in the title.
I tried to change const umap_int::mapped_type & to const int & which did not work either. The standard example of returning a const reference to a variable of simple datatype (int, double, ...) worked.
#include <unordered_map>
using namespace std;
typedef unordered_map<int, int> umap_int;
class class_A{
public:
class_A(){
for(int k=0; k<3;++k)
M[k] = k;
}
const umap_int::mapped_type & get_M(int key) const{
return M[key];
}
private:
umap_int M;
};
int main(){
class_A A;
return 0;
}
Inside const method you can only call for M its const member functions. Both unordered_map::operator[] overloads are non-const - reference. So you cannot use it inside const get_M. You could remove const qualifier from get_M signature, or use find which has const overload but then you need to handle a case when mapped value doesn't exist for the passed key:
const umap_int::mapped_type & get_M(int key) const {
//return M[key];
auto it = M.find(key);
if (it != M.end())
return it->second;
// do sth here ...
// throw exception
// make static variable with default value which will be accessed
}
I am trying to write a graph data structure implementation that I feel satisfied with. (Maintain adjacency lists as sets instead of linked lists.) Anyways, I tried to use references and iterators and wrote this:
#include <iostream>
#include <string>
#include <set>
#include <stack>
class Vertex {
std::string name;
std::set<Vertex> edges;
public:
Vertex(std::string name) : name(name) {}
std::string vertexName() const {
return name;
}
std::set<Vertex> outEdges() const {
return edges;
}
void addEdge(const Vertex& other) {
edges.insert(other);
}
void removeEdge(const Vertex& other) {
edges.erase(other);
}
int outDegree() {
return edges.size();
}
};
bool operator<(const Vertex& v1, const Vertex& v2) {
return (v1.vertexName().compare(v2.vertexName()) < 0);
}
void DFS(const Vertex& v) {
std::stack<Vertex*> stack;
std::set<Vertex*> visited;
stack.push(&v); // error1
visited.insert(&v); // error2
while (!stack.empty()) {
Vertex* vert_ptr = stack.top();
stack.pop();
std::cout << vert_ptr->vertexName() << std::endl;
//
for (std::set<Vertex>::iterator iter = vert_ptr->outEdges().begin(); iter != vert_ptr->outEdges().end(); iter++) {
if (visited.find(&(*iter)) != visited.end()) { // error3
stack.push(&(*iter)); // error4
visited.insert(&(*iter)); // error5
}
}
}
}
int main() {
Vertex a = Vertex("a");
Vertex b = Vertex("b");
Vertex c = Vertex("c");
DFS(a);
getchar();
return 0;
}
I am getting the following errors:
error1: E0304 no instance of overloaded function "std::stack<_Ty, _Container>::push [with _Ty=Vertex *, _Container=std::deque<Vertex *, std::allocator<Vertex *>>]" matches the argument list
error2: E0304 no instance of overloaded function "std::set<_Kty, _Pr, _Alloc>::insert [with _Kty=Vertex *, _Pr=std::less<Vertex *>, _Alloc=std::allocator<Vertex *>]" matches the argument list
error3: E0304 no instance of overloaded function "std::set<_Kty, _Pr, _Alloc>::find [with _Kty=Vertex *, _Pr=std::less<Vertex *>, _Alloc=std::allocator<Vertex *>]" matches the argument list
error4: E0304 no instance of overloaded function "std::stack<_Ty, _Container>::push [with _Ty=Vertex *, _Container=std::deque<Vertex *, std::allocator<Vertex *>>]" matches the argument list
error5: E0304 no instance of overloaded function "std::set<_Kty, _Pr, _Alloc>::insert [with _Kty=Vertex *, _Pr=std::less<Vertex *>, _Alloc=std::allocator<Vertex *>]" matches the argument list
I am realizing that I do not understand references as well as I thought I did. I used google, and the hits I got reiterate what I understand about references, but do not touch on the part I do not understand (which is causing those errors).
I also dereferenced the iterators, and then used & to get the addresses of the actual objects the iterators are pointing to, and do not know if I am misunderstanding the way iterators work, or if it is just a problem with references.
I would appreciate it if someone could point me towards a good reference on all of this. :(
In your case void DFS(const Vertex& v) v is a reference to a var which is constant. In other words, you promised that the function will not modify the object.
std::stack<Vertex*> stack;
std::set<Vertex*> visited;
The above are containers of pointers to an object, which is not a constant and therefore is modifiable.
Here you are trying to violate an agreement. You are trying to allocate a pointer to a constant object v in a container which is intended for pointers to modifiable objects. If this is would have been allowed, you would be able to modify the value referenced by v through the pointer. So, it is not allowed and the compiler produces an error here.
stack.push(&v); // error1
visited.insert(&v); // error2
so, you needed to declare containers with pointers to the constants:
std::stack<const Vertex*> stack;
std::set<const Vertex*> visited;
now, the visited.find(&(*iter)) has to do with the implementation of the set::iterator. Apparently the value returned by operator '*' referenced a constant value, causing another conversion attempt from 'const' to non-const.
So, declaring stack and visited with const Vertex * argument should solve your compilation issues.
This is excerpt from my code:
std::map<int, std::pair< const int, const std::vector<POINT_3d> > > m_srcHitData;
void addHit( const int edgeId, const int hit )
{
m_srcHitData[edgeId] = std::make_pair( hit, std::vector<POINT_3d>() );
}
I keep getting the error:
stl_pair.h(180): error: no operator "=" matches these operands
operand types are: const std::vector<POINT_3d, std::allocator<POINT_3d>> = const std::vector<POINT_3d, std::allocator<POINT_3d>>
second = __p.second;
^
detected during instantiation of "std::pair<_T1, _T2> &std::pair<_T1, _T2>::operator=(const std::pair<_U1, _U2> &)
What does that mean? I tried different approaches but still getting this or similar error. Thank you!
Well, m_srcHitData[edgeId] is a pair with a const vector member. You can't simply assign to it, because that means assigning to the const vector, which is not possible...
As for what you can do about it, see:
How to create a std::map of constant values which is still accessible by the [] operator?
As #FrancisCugler suggests, that could be, for example, writing:
m_srcHitData[edgeId].insert( std::make_pair( hit, std::vector<POINT_3d>() );
However, if your vectors are long, you might not actually want to copy all that data around.
This part in your code kind of looks ugly...
std::map<int, std::pair< const int, const std::vector<POINT_3d> > > m_srcHitData;
You could try restructuring your code a little.
struct Pair {
unsigned int key_;
std::vector<POINT_3d> points_;
Pair() {} // Empty Default
Pair( const unsigned int& key, const std::vector<POINT_3d>& points ) :
key_(key),
points_( points )
{}
};
Then...
std::map<unsigned, Pair> m_srcHitData;
void addHit( const int edgeId, const int hit ) {
m_srcHitData[edgeId] = Pair( hit, std::vector<POINT_3d>() );
}
I made this short program to simulate a similar structure only I used strings in place of your std::vector<POINT_3d>
#include <string>
#include <iostream>
#include <map>
struct Pair {
unsigned key_;
std::string value_;
Pair() {}
Pair( const unsigned int& key, const std::string& value ) :
key_( key ),
value_( value ) {}
};
class MyClass {
public:
std::map<unsigned, Pair> myMap_;
void addValue( const unsigned int& key, const std::string& value ) {
myMap_[key] = Pair( key, value );
}
};
int main() {
MyClass myClass;
myClass.addValue( 1, "Hello" );
myClass.addValue( 2, "World" );
typedef std::map<unsigned, Pair>::iterator Iter;
Iter it = myClass.myMap_.begin();
for ( ; it != myClass.myMap_.end(); ++it ) {
std::cout << "Key: " << it->first << " Pair-Key: " << it->second.key_ << " Pair-value: " << it->second.value_ << std::endl;
}
std::cout << "\nPress any key and enter to quit." << std::endl;
char c;
std::cin >> c;
}
You can use the above, except substitute your objects of vector<T> with the strings.
I also used public interface on both the struct and class for simplicity of demonstration. Normally the container in the class would be either protected or private with accessory functions.
EDIT This is to help construct the map first. Once you have the map working then you can modify it to add in the const storage types if needed, but they can be tricky to work with. Refer to the link in einpoklum's answer.
If you are working with the newer versions of C++ you can change these lines of code:
typedef std::map<unsigned, Pair>::iterator Iter;
Iter it = myClass.myMap_.begin();
into this:
auto it = myClass.myMap_.begin();
I'm developing this program to run Dijkstra's Algorithm with an heap implementation and I want it to be as versatile as it can be so I'm using function pointer in order to avoid code repetition. This is the error that it pops. I'm using the stl make_heap
"Type must use '.*' or '->*' to call pointer-to-member function in '__comp (...)', e.g. '(... ->* __comp) (...)' "heap.h C/C++ Problem
Here is Dijkstra's Algorithm:
void Graph::dijkstraAlg(Vertex* ini, Vertex* fin, void(Graph::*weight_filler)(void), bool(Graph::*pq_order)(const Vertex* &, const Vertex* &)){
for(unsigned int i = 0; i < vertexs.size(); i++) {
vertexs[i]->path = NULL;
vertexs[i]->holder = MAX_INT_VALUE;
vertexs[i]->processing=false;
}
(this->*weight_filler)();
Vertex* v=ini;
v->holder = 0;
v->processing = true;
vector<Vertex*> pq;
pq.push_back(v);
make_heap(pq.begin(),pq.end(),pq_order);
while(!pq.empty()){
v=pq.front();
pop_heap(pq.begin(),pq.end());
pq.pop_back();
for(unsigned int u=0; u < v->adj.size(); u++){
Vertex* w = v->adj[u]->dest;
if((v->holder+v->adj[u]->weight) < w->holder){
w->holder=v->holder + v->adj[u]->weight;
w->path=v;
if(!w->processing){
w->processing=true;
pq.push_back(w);
}
}
make_heap(pq.begin(),pq.end(),pq_order);
}
}
return;}
The error is in the make_heap and I can't figure it out, any help is appreciated.
Here is the function I'm passing to the make_heap:
bool Graph::regular_PqOrder(const Vertex* &v, const Vertex* &u){
return v->holder > u->holder;}
This is how I call the algo:
dijkstraAlg(i,f,&Graph::price_WeightFiller,&Graph::regular_PqOrder);
If you need more information just tell me and I edit it.
Thank you pal's
You're passing the wrong type. std::make_heap takes a functor as the third element, which should satisfy the requirements of Compare, which are that you need:
bool operator()(const Type1&, const Type2&) const;
You are passing in pq_order which is of type:
bool(Graph::*)(const Vertex* &, const Vertex* &)
That's a pointer-to-member, it's not callable without an object of type Graph. Hence the error about "Type must use '.' or '->' to call pointer-to-member". The simplest approach is to simply provide that object, which in your case is this:
using namespace std::placeholders;
std::make_heap(pq.begin(), pq.end(),
std::bind(pq_order, this, _1, _2));
Alternatively, since regular_PqOrder doesn't actually rely on any of the members of other methods of Graph, you could also just be to make it static:
class Graph {
public:
static bool regular_PqOrder(const Vertex* &v, const Vertex* &u)
{
return v->holder > u->holder;
}
};
And pass in Graph::regular_PqOrder now as a function pointer, rather than pointer-to-method.
I have simplified your problem to:
#include <algorithm>
#include <vector>
using namespace std;
class Vertex
{};
class Graph
{
public:
void dijkstraAlg(Vertex* ini, Vertex* fin, void(Graph::*weight_filler)(void),
bool(Graph::*pq_order)(const Vertex*, const Vertex*))
{
(this->*weight_filler)();
struct Comparator
{
private:
Graph* m_g;
bool(Graph::*m_fn)(const Vertex*, const Vertex*);
public:
Comparator(Graph* g, bool(Graph::*fn)(const Vertex*, const Vertex*)) : m_g(g), m_fn(fn)
{}
bool operator()(const Vertex* one, const Vertex* two) const
{
return (m_g->*m_fn)(one, two);
}
};
Comparator comparator(this, pq_order);
vector<Vertex*> pq;
std::make_heap(pq.begin(), pq.end(), comparator);
}
void weight_filler1()
{
}
bool pq_order1(const Vertex*, const Vertex*)
{
return false;
}
};
int main()
{
Graph g;
g.dijkstraAlg(nullptr, nullptr, &Graph::weight_filler1, &Graph::pq_order1);
return 0;
}
The problem is: std::make_heap expects a function pointer- in your case you are passing a pointer to member function thus the issue.
Either you can change the declaration of dijkstraAlg to take in just a static function pointer pq_order or wrap up pq_order in a structure to make it a callable entity in itself like I have done.
Note: you will have to fixup references to pointers in pq_order for make_heap to compile anyway