C++ string.replace generates "No matching function for call" error - c++

Can anyone tell me why this piece of code generates the "No matching function for call" error? I believe that the syntax is correct, I really have no idea why it does not work. I want to replace an occurence of {{some_key}} in Template_ with the matching value of some_key in unordered_map passed to function.
std::string View::Render(const std::unordered_map<std::string, std::string> &model) const {
for(int i = 0; i < this->Template_.length(); ++i){
if(this->Template_[i] == '{' && this->Template_[i+1] == '{'){
int PositionBegin = i;
std::string Key = FindKey();
if(Key.length() > 0) {
std::unordered_map<std::string, std::string>::const_iterator Found = model.find(Key);
if (Found != model.end())
this->Template_.replace(PositionBegin, Key.length()+4, Found->second);
}
}
}
return this->Template_;
}
View class looks as simple as this:
class View {
public:
View(const std::string &Template);
std::string Render(const std::unordered_map<std::string, std::string> &model) const;
std::string Template_;
};
The full error is:
error: no matching function for call to ‘std::__cxx11::basic_string<char>::replace(int&, std::__cxx11::basic_string<char>::size_type, const std::__cxx11::basic_string<char>&) const’ this->Template_.replace(PositionBegin, Key.length()+4, Found->second);

Your function is defined as
std::string View::Render(const std::unordered_map<std::string, std::string> &model) const
Since it is const that means you cannot modify any of the the class members. replace would modify Template_ so you cannot call it.
You have two ways to fix this. You can get rid of the const on the function if you want to be able to manipulate Template or you can declare Template_ as mutable so it can be modified.

The problem is caused by attempting to modify a member variable of a const object.
The member function is a const member function. Hence, this->Template_ is also a const object. You are trying to modify this->Template_ by using
this->Template_.replace(PositionBegin, Key.length()+4, Found->second);
If your program logic requires you to modify this->Template_ in a const member function, you'll have to qualify it with mutable.

Related

I need to access the value within a const std::string& call in a function

I have a quick question regarding C++ and references to values. I have been asked to write a function that takes the input from const std::string& and use the input to perform some tasks. The issue is, I have no idea how to access the value. I know it is a pass-by reference value but I don't know how to access it within the function.
This is the code that I was given:
#include "rle.hpp"
std::string func_send(const std::string&)
{
//Implement !
return {};
}
std::string func_receive(const std::string&)
{
// Implement!
return {};
}
The code you were given makes no sense, at least there is no way to acces the parameter because it has no name. Moreover std::string str = std::string&; is invalid syntax, I don't know what it is supposed to mean. Give the parameter a name:
std::string func_send(const std::string& str)
// ^------------ !!!
{
std::string some_other_string = str;
return {}; // missing semi-colon
}

C++ Class vector error, expression must have pointer type

Currently learning some c++ and unsure why this is giving me "expression must have pointer type".
Mapp.hpp
class RouteMap
{
public:
RouteMap();
string getCurrent_();
void StoreCity(string b);
private:
std::vector<string>* cities();
string current_;
};
mapp.cpp
RouteMap::RouteMap(){}
string RouteMap::getCurrent_()
{
return current_;
}
void RouteMap::StoreCity(string b)
{
cities->push_back(b); //Error
}
std::vector<string> RouteMap::cities()
{
return std::vector<string>();
}
I am attempting to have a vector Cities as a private member so that when I run the member function StoreCity(string x), it would push_back the specific string into Cities.
I'm going to take a stab and say that the problem is cities() is a function and requires parenthesis:
cities()->push_back(b);
Edit Just found the implementation of cities() (silly me). You have another problem, and that is that your declaration and implementation don't match.
// declaration
std::vector<string>* cities();
// implementation. Notice the lack of a pointer type return
std::vector<string> RouteMap::cities()
{
return std::vector<string>();
}
It's also weird that you're returning a new vector each time. You probably want a member variable:
class RouteMap
{
//...
private:
std::vector<string> my_cities;
//...
};
and then return the member variable from there:
std::vector<string>* RouteMap::cities()
{
return &my_cities;
}
Edit2: It has come to my attention that you probably, while you could fix these things like this and get it working, the truth is that you probably don't mean for cities() to be a function at all. You probably mean for it to be a member variable instead:
class RouteMap
{
//...
private:
std::vector<string> cities;
//...
};
This requires no implementation, (aka RouteMap::cities(){}), and you can just use it inside any member function (because it's a private member) like current_.

Calling a function on the this keyword

So in my header file I have these two variables declared as private
private:
char* data;
int len;
and give this to access it
int length() const { return len; }
Then in my cpp file I am trying to override the operators in string implementation like this:
bool MyString::operator>(const MyString& string)
{
//Compare the lengths of each string
if((this.length()) > (string.length())){
return 0;
}
//The given string is shorter
return -1;
}
when I compile this I get this error:
mystring.cpp:263:14: error: request for member ‘length’ in ‘this’, which is of non-class type ‘MyString* const’
From what I can tell by trying to call the .length() on the this is trying to access a variable on the this pointer which is causing a problem, like in this question.
That's fine because I can do this instead:
bool MyString::operator>(const MyString& string)
{
//Compare the lengths of each string
if((this->len) > (string.length())){
return 0;
}
//The given string is shorter
return -1;
}
which compiles fine but now I'm wondering how do you call a function on a this pointer. I thought that because it was a pointer I would have to dereference it first so I tried this:
bool MyString::operator>=(const MyString& string)
{
//Compare the lengths of each string
if((*(this).length()) >= (string.length())){
return 0;
}
//The given string is shorter but not equal
return -1;
}
But again I got this error:
mystring.cpp:273:17: error: request for member ‘length’ in ‘this’, which is of non-class type ‘MyString* const’
It seems like this should have worked fine as I would have dereferenced the pointer into the object it pointed to which does indeed have that method but I seem to be missing something. How would I go about calling a function defined in my class on the this pointer? And is there some functional reason why the way I described above does not work?
if((this.length()) > (string.length())){
This should be
if((this->length()) > (string.length())){
as this is a pointer.Basically this is just a pointer referring to the object on which member function is called. So, you have to use -> for all reference to members of that class.
One more advice stop using variable names which are standard keywords. like string in your case. Had you included std namespace you would have got the reason for not doing so.

Getting information out of a set<MyClass> mySet

So I've got
set<MyClass> mySet;
and in MyClass I have a static int to count the number of compares that happen. I'm trying to get that information out of it but I can't figure out how.
This is what I've tried:
set<MyClass>::iterator it = mySet.begin();
int count = it->getCompareCount();
and
int count = mySet.begin()->getCompareCount();
Neither of those work (Yes I know the are essentially the same exact thing) but I can get that information out of something that is indexed like a std::list or std::vector
Example:
vector<MyClass> myVector;
for (int i = 0; i < 10; i ++)
{
myVector.push_back(MyClass(i,"Some Name", i*2);
}
int count = myVector.at(2).getCompareCount(); //which by default is going to be 0 as no compares have taken place
Can anybody help me? netbeans says "error: passing ‘const MyClass’ as ‘this’ argument of ‘int MyClass::getCompareCount()’ discards qualifiers [-fpermissive]" when I do what I said I tried up above.
EDITS
Declaration of getCompareCount():
int MyClass::getCompareCount()
{
return compareCount;
}
Element in std::set is not mutable after it is inserted into the set. When you dereference an iterator (as in it->), it returns a const reference of the object you put into the set. On the other hand, your definition of getCompareCount() is a non-const instance function meaning it can only be called on non-const instance of the class. Define the function as the following should solve your problem.
int MyClass::getCompareCount() const
{
return compareCount;
}
By the way, since compareCount is a static int, you might want to define the function as static as well so that you can call it using the class instead of having to get an instance to call it.
static int MyClass::getCompareCount()
{
return compareCount;
}
//To Call it
MyClass::getCompareCount()

Passing ifstream not recognized

I'm getting this error message
error: no matching function for call to
HCTree::build(std::basic_ifstream < char, std::char_trait< char>> &)
const
note: candidates are: HCNode* HCTree::build(std::ifstream&) < near
match>
in .cpp
int HCTree::decode(ifstream &in) const {
if(root == NULL) {
root = build(in); <-- error here
}
return aux_decode(in, root); <-- similarly error here too
}
in .hpp
HCNode* build(ifstream &in);
I don't quit understand what am I doing wrong
This looks like a constness problem.
Just a wild guess, but does your HCTree class inherit from HCNode?
You're trying to call a non-const member function from a const function, which is illegal. Furthermore, assuming root is a non-mutable member variable of the HCTree or HCNode class, trying to modify it in the const decode function is also illegal. Try removing the const qualifier from HCTree::decode, since it seems not to be const at all.
Alternatively, if root is not a non-mutable member variable, you could declare HCNode::build as const, assuming it actually doesn't mutate any state.