stl map const_iterator and g++ error - mfc

I'm trying to port some windows"s MFC class to linux because I have to port a windows software to linux.
here is the code I need to port
165: SMapCI it = _s$.find("nchairs");
166: if (it==_s$.end()) return 10;
167: int n = strtoul(it->second.text.GetString(), NULL, 10);
and _s$ and SMapCI are defined like this
typedef std::map<CString, STablemapSymbol> SMap;
SMap _s$;
typedef SMap::const_iterator SMapCI;
So, here is my CString class
class CString {
protected:
std::string str;
public:
CString(const char *_cstr) { str = _cstr;; };
bool operator<(char *_cstr) const { return str < _cstr;};
const char *GetString() { return str.c_str();};
};
And When I build my code, I get following error:
CTablemap/CTablemap.h:167:54: error: passing ‘const CString’ as ‘this’ argument of ‘const char* const CString::GetString()’ discards qualifiers [-fpermissive]
I don't understand this error.
g++ documentation say that
passing 'const OBJECT' as 'this' argument of 'FUNCTION' discards qualifiers
*Message found in GCC version 4.5.1
*you're returning an address
*you're attempting to access a container element with a const_iterator using a member function that has no non-const versions. The non-const function does not guarantee it will not alter the data
but ... my GetString function is defined as "const char *", so I have the keyword const ...
So I don't get it ... any help will be more than welcome
note: I'm using my own CString class instead of directly changing it with std::string because the code I want to port is too huge, and I want to do the minimum modification on it. (and some function defined in CString are not defined in std::string)
thanks in advance for any help !!

Your function signature should be
const char *GetString() const
Notice the last const.
Right now, you're saying, "I'm returning a const char pointer from a non-const CString instance". This is fine, but what you're being asked to do is define a function that can be used on a const CString instance - and that's what the last const (after the function parameter list) does, specify that that function can be called on a const CString.
You may want both versions of that function, but in particular, you need it here because the const_iterator exposes its contents as const objects, regardless of what they are inside the container itself.

The prototype of GetString should be:
const char *GetString() const;
The first const means that the caller cannot modify the returned value. The second const means that this method can be called for a const CString.
On the other hand, I would also change the operator< and use:
bool operator<(const char *_cstr)

Related

How to convert `const char* const` to `const char*`

I have a const char* const which I need to pass to a method that expects a const char*. How do I do that?.
Also, there is an API that accepts const char **. How do I change in this case?. I tried
const char* const abc="something;
otherAPIThatExpectsConstCharStarStar( &const_cast( abc ) ).
But on linnux this is failing with 'lValue required as '&' operator'.
You don't need to. The last const identifies the type of the variable which holds the string. This means that you cannot modify the variable. But you can freely assign it to some other variable or pass as an argument which doesn't need to be constant anymore.
You really don't need to,as you can see ,when you give an argument to a method,the method will create a copy of the argument,so inside the method, it can only changes the copy,not the original one,unless you pass an address of reference, so,now you have a pointer , it must not be changed ,that's ok ,just pass it to the method, it won't be changed , as I've said.
#include<iostream>
using namespace std;
void fun(const char *p)
{
char tt[10]="dsds";
p=tt;
cout<<"inside_fun"<<endl;
}
int main()
{
int i;
char here[10]="212121";
const char * const pp=here;
fun(pp);
cout<<pp<<endl;
}
This is a bad style code, but it shows the point, just pass it, and change it inside the method,no problem.
#include <iostream>
#include <string>
std::void setString(const char *p) {
std::cout << p << std::endl;
}
int main() {
const char* const cStr ="hello";
setString(cStr);
}

c++ QVector/Vector issues... const... discards qualifiers

I setup a class called tagToken.
It has setter functions, one is void setString(QString)
I have it defined/declared as such
.h file
void setString(QString string);
Private:
QString stringOfTagToken ;
.cpp file
void tagToken::setString(QString string)
{
stringOfTagToken = string;
}
When I try to run this code:
if (linePosition == 1)
{
QVector<tagToken> temp(0);
//errors
//temp.at(0).setString(line);
temp.at(0).setString("test");
//tags.at(0).setString(line);
//tags.push_back();
tagTokenCounter++;
}
I get this error:
C:\Dev\DiffMatchPatch\diffmatchpatch.cpp:316: error: passing 'const tagToken' as 'this' argument of 'void tagToken::setString(QString)' discards qualifiers [-fpermissive]
temp.at(0).setString("test");
QVector's at function returns data as const. Use at when you don't want to (accidentally) change the vector data, or operator[] in general.
temp[0].setString("test");
QVector::at() returns a const ref to your data, you cannot call a non-const method like setString on that
From http://qt-project.org/doc/qt-4.8/qvector.html#at
const T & QVector::at ( int i ) const
Returns the item at index position i in the vector.
i must be a valid index position in the vector (i.e., 0 <= i < size()).
Consider using operator[] instead

Encapsulation and const issues

I have a problem in a c++ assignment that cannot be solved. Lets say this - the program works only if the membervariable (a pointer to an char-array) i public. But according to the rules it must be private and one should be able to access it through a public member-method.
Here is the definitions:
private:
char* _strPtr();
int _strLen;
public:
const char* getString();
const char* String::getString() {
return _strPtr;
}
And here in an overloaded member-function the problem arises
const String operator+(const String string, const char *ch) {
String temp;
strcpy(temp.getString, string.getString());
strcat(string.getString(), ch);
return temp;
}
I get error-messages such as
invalid arguments Candidates are ; unsigned int strlen(const char *)
invalid arguments Candidates are ; const char* getString()
I cannot see how this could be solved. I have really tried with everything. Would be glad if someone could come with good tips.
As - I said in th beginning - the program works, but after encapsulating the membervariable and putting a const ahead of the function - it doesn't work any more.
You are defining char* _strPtr();, which is the definition of a function returning a char*. Probably what you meant was to define char* _strPtr;

C++ V8 object context

I'm trying to perform a callback in C++ (where C++ is running as part of a node.js program). The callback is to a 3rd party library, where it will call the callback when it has data to pass.
The problem I appear to be having is with variable types:
static void sensorEventCallback(const char *protocol, const char *model,
int id, int dataType, const char *value, int timestamp,
int callbackId, void *context)
{
//process the data here
}
Handle<Value> sensorEvents( const Arguments& args ) {
HandleScope scope;
...
callbackId = tdRegisterSensorEvent(
reinterpret_cast<TDSensorEvent>(&telldus_v8::sensorEventCallback),
Context::GetCurrent()->Global());
}
The error I'm getting:
error: cannot convert ‘v8::Local<v8::Object>’ to ‘void*’ for argument
‘2’ to ‘int tdRegisterSensorEvent(void ()(const char, const char*,
int, int, const char*, int, int, void*), void*)’
It appears to be struggling with argument 2 which is the context. Any thoughts on how I can convert the V8 object to one that tdRegisterSensorEvent will accept?
Snooping a bit, that GetCurrent appears to be defined in the V8 header to return a Local<Context>:
v8.h on GitHub, location of GetCurrent() in the Context object definition
This Local<T> is a template for a "lightweight, stack allocated handle", derived from a base class Handle<T>:
v8.h on GitHub, definition of Local
v8.h on GitHub, definition of Handle
So seems you've got a Context pointer whose lifetime is being managed by something called a HandleScope. If you pull the context pointer out and save it to use in a callback later, it may or may not still exist at the time the call is made.
If you know all the callbacks will happen before it's freed by the handle scope, you can try getting the pointer out using the dereference operator overload and passing it:
v8.h on GitHub, T* Handle::operator*()
But you may not have this guarantee.
As n.m. says I would guess the address of the context object should be passed. You can then cast that back in your callback
void telldus_v8::sensorEventCallback(const char *protocol, const char *model,
int id, int dataType, const char *value, int timestamp,
int callbackId, void *context)
{
v8::Local<v8::Object>* ctx_ptr = static_cast<v8::Local<v8::Object>*>(context);
//process the data here
}
v8::Local<v8::Object> ctx = Context::GetCurrent()->Global();
callbackId = tdRegisterSensorEvent(
reinterpret_cast<TDSensorEvent>(&telldus_v8::sensorEventCallback),
&ctx);

passing ‘const Link’ as ‘this’ argument of ‘std::string GetAttribute(std::string)’ discards qualifiers

I'm getting an odd error with parts of the NS-3 API. Here is my error message:
error: passing ‘const ns3::TopologyReader::Link’ as ‘this’ argument of ‘std::string ns3::TopologyReader::Link::GetAttribute(std::string)’ discards qualifiers
And here is the code causing the issue:
TopologyReader::ConstLinksIterator iter;
int num = 0;
for (iter = topologyReader->LinksBegin (); iter != topologyReader->LinksEnd(); iter++, num++)
{
std::istringstream fromName(iter->GetFromNodeName ());
std::istringstream toName (iter->GetToNodeName ());
iter->GetToNodeName();
std::string w = "Weight";
std::string weightAttr = (iter)->GetAttribute(w); // <- error
/* snip */
}
I think it might have to do with the fact that GetAttribute(std::string) is not a const function, according to the documentation for TopologyReader::Link, while the other functions, GetFromNodeName(void) and GetToNodeName(void) are declared as const functions. However, I'm not sure how to fix this problem.
Edit:
The function signatures are as shown (from the linked documentation):
std::string ns3::TopologyReader::Link::GetFromNodeName (void) const
std::string ns3::TopologyReader::Link::GetToNodeName (void) const
std::string ns3::TopologyReader::Link::GetAttribute (std::string name)
Your analysis is correct. The obvious fix is to make GetAttribute be a const function. Its name suggests it should be const. It might not be in your power to change that code, though.
The alternative is to find some way of getting a non-const object to call the function on. Maybe you could declare iter as a LinksIterator instead of a ConstLinksIterator.
As a last resort, you could try using const_cast to tell the compiler that it's really safe to call a non-const method on a supposedly const object.