I wrote the following function, which is supposed to allow me to append some input QByteArray data to a private QByteArray inside of my class:
void addQByteArray(QByteArray* array)
{
p_commandArray.append(array);
}
My understanding is that the append function should also accept a QByteArray as a parameter, but I'm getting this error when I try to compile:
error: invalid conversion from ‘QByteArray*’ to ‘char’ [-fpermissive]
p_commandArray.append(array);
^
What am I doing wrong here?
Yes QByteArray::append has an overload that you can pass a QByteArray (more precicelsy a const QByteArray&), but what you attempt to pass is a pointer to QByteArray.
Either
void addQByteArray(QByteArray& array)
{
p_commandArray.append(array);
}
or
void addQByteArray(QByteArray* array)
{
p_commandArray.append(*array);
}
Prefer the first (passing a reference), because using pointers only makes sense when a nullptr is a valid parameter, but when you pass a nullptr you shall not dereference it.
The error message you get is due to another overload of append that takes a char as parameter.
QByteArray::append accepts const QByteArray&, but you give it a pointer. Give it an object:
void addQByteArray(QByteArray* array) {
p_commandArray.append(*array);
// ^ dereference
}
Related
I want to write portable code in c++11 for different CPU's (actually MCU's). As some CPU's does not support reading program data directly through it's memory address space (such as Atmel AVR), I need a solution that calls a function either with a direct address, or with a custom made Stream pointer to read the data trough some external storage.
Consider this code as the custom library:
class IStream
{
public: virtual char ReadChar();
};
class ConstMemoryStream : public IStream
{
const char* Position;
public: ConstMemoryStream(const char* startAddress)
{
Position = startAddress;
}
public: char ReadChar() override
{
return *Position++;
}
};
void Send(char data) { } // Send data to serial port
Now, I want to implement a function that takes either a memory address, or a Stream to read the data from:
// const parameter is needed here, otherwise error: invalid initialisation of non-const reference of type 'IStream&' from an rvalue of type 'IStream'
void PrintMessage(const IStream& stream)
{
while (true) // TODO: end condition
//Send(stream.ReadChar()); // this gives an error because i need to use a const parameter: passing 'const IStream' as 'this' argument discards qualifiers
Send( ((IStream*)&stream)->ReadChar() ); // this works, this actually bypass the error above. IS THIS OK?????
}
void PrintMessage(char* address); // overload to use memory instead of stream. implementation not important here
Next, I want to call PrintMessage with a Stream, but this stream needs to be created inline, and is not needed anymore outside the PrintMessage function:
int main(void)
{
// Requirement: ConstMemoryStream needs to be created and passed INLINE PrintMessage
PrintMessage(ConstMemoryStream("Hello!")); // This works only if i put const in PrintMessage parameter.
}
All the code above compiles and works, but my main concern is that I need to use a const parameter in the PrintMessage function (otherwise I get an error). Because of this, I need to do an ugly cast:
Send( ((IStream*)&stream)->ReadChar() );
This basically makes the parameter non-const to avoid the error. But is there a better solution to do this "legally"?
The stream instance itself cannot be const because it advances it's position internally, but c++ requires to pass it as const because it's an inline temporary variable which is always considered as an rvalue.
I don't see any harm from a temporary variable to modify itself, after the PrintMessage function return it's discarded anyway.
The inline requireWhat I finally want to do is this:
#ifdef CPU_AVR
#define CSTR(str) ConstMemoryStream(PROGMEM str) // the PROGMEM attribute puts the text in a separate space not accessible in regular memory
#elif defined CPU_SAM
#define CSTR(str) (char*)str
#endif
int main2(void)
{
// If the CPU does not support direct address mapping to it's FLASH space, pass a stream instead of a direct memory pointer
PrintMessage(CSTR("Hello"));
}
Any idea on how to do this properly without casting to discard the error? Or is the current code above acceptable?
With C++11 you can simply take an rvalue reference as a parameter.
void PrintMessage(IStream && stream)
rvalue references will bind to temporaries, and will mostly be indistinguishable from lvalue references, in this context.
Either your interface is wrong, or your usage is wrong. Currently you are const_casting your stream. If you ever pass a const IStream object, that would be undefined behaviour.
Either:
class IStream
{
public: virtual char ReadChar() const;
};
Or:
void PrintMessage(IStream& stream)
{
while (true) // TODO: end condition
Send(stream.ReadChar());
}
void PrintMessage(IStream&& stream)
{
while (true) // TODO: end condition
Send(stream.ReadChar());
}
int main(void)
{
PrintMessage(ConstMemoryStream("Hello!"));
}
I though that I understood iterators and addressing etc. but obviously not. See my below code below which is purely an example.
I need to be able to pass by pointer or reference each structure of mystructs to MyFunc(). The function should be able to update the actual structure that is passed, and not by copy or value.
I receive the compiler error :
error: cannot convert 'MY_STRUCT' to 'MY_STRUCT*' for argument '1' to 'void MyFunc(MY_STRUCT*)'
If I just pass the iterator address, this also doesn't work.
What is the correct way to do this. Thanks in advance.
typedef struct
{
int var1;
int var2;
std::string name;
}MY_STRUCT;
std::list<MY_STRUCT> mystructs;
void MyFunc(MY_STRUCT*)
{
// Do something
}
// populate the list with structs etc.. not included here
//.....
for (std::list<MY_STRUCT>::iterator it = mystructs.begin();it != mystructs.end(); ++it)
{
MyFunc(*it);
}
Passing by reference in C++ is done with:
void MyFunc(MY_STRUCT&)
{
// Do something
}
So your call would be correct, what you currently want is to pass the pointer, which you can do with dereferencing the dereferenced iterator (by passing the address of the dereferenced object):
void MyFunc(MY_STRUCT*)
{
// Do something
}
// populate the list with structs etc.. not included here
//.....
int main() {
for (std::list<MY_STRUCT>::iterator it = mystructs.begin();it != mystructs.begin(); ++it)
{
MyFunc(&*it);
}
}
Your function requires a pointer, use & to get the address of something.
MyFunc(&*it);
*it returns a reference to the MY_STRUCT object, you need to use & to convert that reference to a pointer. This is normal, the fact that you are using iterators makes no difference at all.
The alternative (maybe better in C++) would be to convert your MyFunc function to take a reference instead of a pointer.
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
In my main function I create an array of objects of a certain class "Menu"
And when I call a function I want to provide a pointer to that array.
Menu menu[2];
// Create menu [0], [1]
Function(POINTER_TO_ARRAY);
Question: What is the correct way to write the Function parameters?
I try:
Function(&menu);
and in Header file:
void Function(Menu *menu[]); // not working
error: Cannot convert parameter 1 from Menu(*)[2] to Menu *[]
void Function(Menu * menu); // not working
error: Cannot convert parameter 1 from Menu(*)[2] to Menu *[]
and I can't come up with any other way to do this and I can't find a solution to this particular problem.
Simply, I want to be able to access the Menu array within the function through a pointer. What are the difference in normal pointer to a pointer to an array?
Declaration:
void Function(Menu* a_menus); // Arrays decay to pointers.
Invocation:
Function(menu);
However, you would need to inform Function() how many entries are in the array. As this is C++ suggest using std::array or std::vector which have knowledge of their size, beginning and end:
std::vector<Menu> menus;
menus.push_back(Menu("1"));
menus.push_back(Menu("2"));
Function(menus);
void Function(const std::vector<Menu>& a_menus)
{
std::for_each(a_menus.begin(),
a_menus.end(),
[](const Menu& a_menu)
{
// Use a_menu
});
}
Either by const or non-const pointer
void Function(Menu const* menu);
void Function(Menu* menu);
...or by const or non-const reference
void Function(Menu const (&menu)[2]);
void Function(Menu (&menu)[2]);
which can be generalized to a template so that the array size will be deduced by the compiler:
template<size_t N> void Function(Menu const (&menu)[N]);
template<size_t N> void Function(Menu (&menu)[N]);
Always call as Function(menu);
Should work if you use
void Function(Menu * menu);
and call using
Function(menu);
instead of
Function(&menu);
passing the array name causes it to decay to a pointer to the type contained in the array. However, as #hmjd says in his answer you will also need to pass the array size, so his suggestion of using a vector is favourable if this option is open to you.
You can use
Function((void *) whatever_pointer_type_or_array_of_classes);
in your main.
And in the function:
type Function(void * whatever)
{
your_type * x =(your_type *) whatever;
//use x
....
x->file_open=true;
....
}
For example, if I have the following:
void foo(string* s)
{
bar(s); // this line fails to compile, invalid init. error
}
void bar(const string& cs)
{
// stuff happens here
}
What conversions do I need to make to have the call the bar succeed?
Change it to:
bar(*s);
void foo(string* s)
{
bar(*s);
}
s points to a string, and bar requires a (reference to a) string, so you need to give bar what s points to. The way you spell "what s points to" is *s.
When converting a pointer to a reference it is important to make sure that you are not trying to convert a NULL pointer. The compiler has to allow you to do the conversion (because in general it can't tell if it is a valid reference).
void foo(string* s)
{
if(0 != s){
bar(*s);
}
}
The * operator is the inverse of the & operator. To convert from a reference to a pointer your use & (address of). To convert a pointer to a reference use * (contents of).