The code was as below
#include <set>
#include <iostream>
#include <string>
#include <memory>
using namespace std;
class Quote {
public:
int getnum() {
return num;
}
private:
int num;
};
class basket {
public:
void add_item(const shared_ptr<Quote> &b) {
setQuo.insert(b);
}
private:
static bool compare(shared_ptr<Quote> &l, shared_ptr<Quote> &r) {
return l->getnum() < r->getnum();
}
multiset<shared_ptr<Quote>, decltype(compare)*> setQuo{compare};
};
int main()
{
cout << "start" << endl;
}
I found thatsetQuo.insert(b);will lead complie error. Complie error was as below
*/usr/include/c++/7/bits/stl_tree.h:2069:51: error: binding reference of type ‘std::shared_ptr<Quote>&’ to ‘const key_type {aka const std::shared_ptr<Quote>}’ discards qualifiers
__x = _M_impl._M_key_compare(__k, _S_key(__x)) ?*
*/usr/include/c++/7/bits/stl_tree.h:1750:10: error: binding reference of type ‘std::shared_ptr<Quote>&’ to ‘const std::shared_ptr<Quote>’ discards qualifiers*
The code was looks right for me, this question is really confused me.
Your compare function is not supposed to change the elements it's comparing so take the arguments by const&:
static bool compare(const shared_ptr<Quote> &l, const shared_ptr<Quote> &r) {
return l->getnum() < r->getnum();
}
Demo
Related
"this discards qualifiers", what does it mean?
#include <iostream>
using namespace std;
#include <iostream>
using namespace std;
class b
{
public:
void show( b &ob)
{
//this =ob;
cout<<"show";
}
};
int main()
{
b const ob;
b ob1;
ob.show(ob1);
// your code goes here
return 0;
}
prog.cpp: In function ‘int main()’:
prog.cpp:23:14: error: passing ‘const b’ as ‘this’ argument discards qualifiers [-fpermissive]
ob.show(ob1);
^
Here you've declared ob to be a const object:
b const ob;
But here you are calling a member function (show) that is not marked as const:
ob.show(ob1);
Mark member functions that does not alter the object (*this) as const:
void show( b &ob) const // <- like this
{
//this =ob;
cout<<"show";
}
In this particular case, I also recommend that you change show so it does not take any arguments and only show the contents of *this:
#include <iostream>
class b
{
private:
int example_of_a_member_variable;
public:
// example of a converting constructor
explicit b(int value) : example_of_a_member_variable(value) {}
void show() const
{
std::cout << example_of_a_member_variable << '\n';
}
};
int main() {
b const ob(1234);
ob.show(); // prints 1234
}
I have in a C++ class the following :
I want to use an iterator to have an element of the questions list at a time by calling the getNextQuestion() function after checking if the iterator is still valid by calling isValid(). It gives me the following terrible error :
passing ‘const iterator {aka const std::_List_iterator<domain::Question>}’ as ‘this’ argument of ‘std::_List_iterator<_Tp>::_Self&
std::_List_iterator<_Tp>::operator++() [with _Tp = domain::Question,std::_List_iterator<_Tp>::_Self =
std::_List_iterator<domain::Question>]’ discards qualifiers [-fpermissive]
#ifndef TESTREPOSITORY_H_
#define TESTREPOSITORY_H_
#include <iostream>
#include <iterator>
#include <list>
#include <algorithm>
#include <fstream>
#include "../domain/question.h"
using namespace domain;
namespace repository{
template<class T>
class TestRepository{
std::string file;
std::list<T> questions;
typename std::list<T>::iterator it;
public:
TestRepository(std::string& file=""):file(file){
this->questions = this->getQ();
this->it = this->questions.begin();
};
std::list<T> getQ() const{
std::list<T> listq;
using namespace std;
string line;
std::ifstream fin(file.c_str());
while(fin.good()){
Question q;
fin >> q;
listq.push_back(q);
}
fin.close();
return listq;
}
const bool isValid() const{
return this->it != this->questions.end();
}
const T getNextQuestion() const{
T q = (*this->it);
++this->it;
return q;
}
};
}
#endif /* TESTREPOSITORY_H_ */
Here is the code where I call these funcitons,maybe here is the problem coming from :
#include "TestController.h"
#include "../domain/test.h"
#include <iostream>
#include <list>
#include <iterator>
namespace controller{
TestController::TestController(repository::TestRepository<domain::Question>* repo,int testId){
this->repo = repo;
this->testId = 0;
}
const test TestController::getCurrentTest() const{
test test(this->testId,0,0);
return test;
}
const bool TestController::isValid() const{
return this->repo->isValid();
}
const Question TestController::getNextQuestion() const{
return this->repo->getNextQuestion();
}
}
Here:
const T getNextQuestion() const{
T q = (*this->it);
++this->it;
return q;
}
You are changing the field it and you're not supposed to, because the method is const. If you want to use const only in the meaning that your "repository" is not modified, but its internal iterator is irrelevant you can use the mutable keyword:
mutable typename std::list<T>::iterator it;
You are trying to modify a member in a const member function, which is forbidden (thats the point of const member functions) :
const T getNextQuestion() const{
T q = (*this->it);
++this->it; // << Here
return q;
}
This method should be non const, or consider having your member iterator be mutable :
mutable typename std::list<T>::iterator it;
The following code won't compile because of "error: no matching function for call to ‘mem_fun_ref()’" (gcc version 4.4.6).
#include <vector>
#include <string>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
class toto
{
char v[10];
public:
toto(char* t) { memcpy(v, t, 9); }
bool test(const char* var) const { return !strncmp(var, v, 9); }
bool test(const string& var) const { return test(var.c_str()); }
};
int main()
{
vector<toto> t;
t.push_back("1");
t.push_back("2");
string name("2");
vector<toto>::iterator it = remove_if(t.begin(), t.end(),
bind2nd(mem_fun_ref(&toto::test), name)); // <= error
t.erase(it, t.end());
return 0;
}
I found a workaround: creating a
bool testZ(const string& var) const { return testZ(var); }
But I can't seem to find the correct template parameters, if that's even possible, to give to mem_fun_ref (or bind2nd?) to make it compile without my workaround.
Is there anyway to achieve this without my workaround, or is the workaround the "preferred" method?
You should be able to cast it according to C++ overloaded method pointer:
bind2nd(mem_fun_ref((bool (toto::*)(const string&) const) &toto::test), name));
Is it possible to write const function with apply_visitor inside?
For example, this code compiles without errors:
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <boost/variant.hpp>
using namespace std;
typedef boost::variant<int,string> vTypeVariants;
struct vType_toN : boost::static_visitor<int>
{
int operator()(int& i) const {
return i;
}
int operator()(const string& str) const{
return str.length();
}
};
class vType{
public:
vType(const int& src) : data(src){}
vType(const std::string& src) : data(src){}
int getLength(){
return boost::apply_visitor(vType_toN(),data);
}
private:
vTypeVariants data;
};
int main(int argc, char ** argv)
{
vType x = string("2");
printf("L=%d",x.getLength());
return(0);
}
Unless you will add const to getLength():
int getLength() const{
return boost::apply_visitor(vType_toN(),data);
}
In such case an error with vast description (2 pages) appears complaining about problem with initializing first argument.
So, the question is: How to use apply_visitor inside const function?
Found out myself.
Forgot const before int in static_visitor class operator definition.
Maybe someone will find this useful as it was not easy to find this out (my original class is much bigger).
I am having issues with the following snippet of code
string const& symbol::at(int index) const {
assert(index<symbol_data.vector::size());
return symbol_data.vector::at(index);
}
Here, symbol_data is a private member of the class and is a vector
::at is a member function in the symbol class that I have defined.
When I try compiling this code, I get the following error messsage:
error: ‘template<class _Tp, class _Alloc> class std::vector’ used without template parameters
However, there is no error if I change the function prototype to
string symbol::at(int index) {...}
Does anybody know how I can get STL vectors to work properly with const references?
Your code as I'm writing this:
string const& symbol::at(int index) const {
assert(index<symbol_data.vector::size());
return symbol_data.vector::at(index);
}
Instead of symbol_data.vector:: write just symbol_data..
Cheers & hth.,
I can't reproduce your problem; the following compiles and works fine on VS2010 express.
#include <cassert>
#include <iostream>
#include <string>
#include <vector>
class symbol
{
std::vector<std::string> symbol_data;
public:
symbol()
{
symbol_data.push_back( "Str1" );
symbol_data.push_back( "Str2" );
}
std::string const& at( int index ) const
{
assert( index < symbol_data.vector::size() );
return symbol_data.vector::at( index );
}
};
int main()
{
symbol s;
std::cout << s.at( 0 ) << std::endl;
std::cin.get();
return 0;
}