Proper casting of the object in C++, value field is not changing - c++

I have a class:
class Para{
public:
int wrt, liczbaWystapien;
Para(){}
Para(int wrt, int liczbaWystapien){
this->wrt = wrt;
this->liczbaWystapien = liczbaWystapien;
}
Then there is other template class, and I do not know how to cast object to Para, becuase first way does not affect field value at all.
else if (is_same<T, Para>::value){
//dynamic_cast<Node<Para>*>(node)->key.wrt++;//this way no error occured but value of field **wrt** stays the same
node->key.wrt++;//error below
Error 4 error C2039: 'wrt' : is not a member of 'std::basic_string<_Elem,_Traits,_Ax>'
EDIT:
Node* paraNode = static_cast*>(node);
Para para = paraNode->key;
para.wrt = para.wrt + 1;
That gives
Error
4 error C2440: 'static_cast' : cannot convert from 'Node *' to 'Node *'

Something seems weird, because key's type supposed to be Para. What happens if you spell everything out?
Node<Para>* paraNode = dynamic_cast<Node<Para>*>(node);
Para para = paraNode->key;
key.wrt = key.wrt + 1;
Other suggestions: if fore some reason you are sure about the template type, you can use static_cast<> (or reinterpret_cast<>), it's faster than dynamic_cast<>, which really discovers and check the type hierarchy tree.

If you do
Para para = paraNode->key;
you get a copy of the key. Then you increment wrt. If you do a printf following that line, you will probably get the expected value. However if you call this from inside a function then the original paraNode will not be modified.
You need to store key as Para* key then access key.wrt with key->wrt++ then after the function you will get the expected value. I suggest you read on how stack and heap variables work as well as copy constructor in c++

Related

C++ Cast from ‘std::__tuple... {aka ‘unsigned int*’} to ‘uint32_t’ {aka ‘unsigned int’} loses precision

You may have to forgive me as I'm new to C++ and may have made some fundamental errors with the code I have worked up so far.
static tuple<read_result, uint8_t*> m_scan_record(bool skip, uint32_t& size, FILE* file)
{
read_result result;
tuple<read_result, uint32_t*> rd_rec_size_result = m_read_generic_t<uint32_t>(file);
result = (read_result)get<0>(rd_rec_size_result);
if (result != read_success )
{
return tuple<read_result, uint8_t*>(result, nullptr);
}
size = (uint32_t) get<1>(rd_rec_size_result);
if ( skip )
{
fseek(file, size, SEEK_CUR);
}
// ...
}
template<typename T>
static tuple<read_result, T*> m_read_generic_t(FILE* file)
{
T ret = 0;
read_result result = m_read_from_file_to_buffer(&ret, sizeof(T), file);
if (result == read_success)
{
return tuple<read_result, T*>(result, &ret);
}
return tuple<read_result, T*>(result, nullptr);
}
When I compile this code I am getting this error:
cast from ‘std::__tuple_element_t<1, std::tuple<read_result, unsigned int*> >’ {aka ‘unsigned int*’} to ‘uint32_t’ {aka ‘unsigned int’} loses precision [-fpermissive]
My intentions and what I am expected to do/happen:
In the declaration of m_scan_record, the size argument is declared with a & which is intended to allow me to pass the value by reference, analogous to using the REF c# keyword
I make a call to generic (template) function m_read_generic_t which is called with the specified type <unit32_t> and therefore (according to its definition) will return a type of tuple<read_result, uint32_t*>
Once I have the tuple returned by m_read_generic_t, I want to take the unit32_t value pointed to by the second value of the tuple, and put that value into the size variable mentioned at point 1, above, which presumably will then be accessible to the calling function one step further up the stack.
From the above points you can hopefully see that my intention (and I appreciate that I may be far away in reality!) is that at this line:
size = (uint32_t) get<1>(rd_rec_size_result);
all I am doing is simply grabbing a 'pointed to' value and putting it into a variable of a matching type, much like the oft-cited textbook example:
uint32_t v = 123;
uint32_t* ptr_to_v = &v;
uint32_t x = ptr_to_v; // x == 123
Clearly this is not what is really going on with my code, though, because if it were, I presume that the cast would be un-needed. But if I remove it, like this:
size = get<1>(rd_rec_size_result);
then I get a compile-time error:
a value of type "std::__tuple_element_t<1UL, std::tuple<read_result, uint32_t *>>" cannot be assigned to an entity of type "uint32_t"
I believe therefore that I am doing something badly wrong - but I can't work out what. Is this to do with the way I am taking the pointer out of the tuple; or is there something else going on when it comes to the getting a uint32_t value from a uint32_t* ?
This is all in a C++ environment on Ubuntu 20.04, FWIW
Many thanks in advance for any/all suggestions; please go easy on me!
tuple<read_result, uint32_t*> rd_rec_size_result = ...
The 2nd member of this tuple, as explicitly declared here, is a pointer to a uint32_t. That's what uint32_t * means, in C++.
size = (uint32_t) get<1>(rd_rec_size_result);
This retrieves the uint32_t * and attempts to convert it to a uint32_t. C++ does not work this way. Although this conversion can be forced your compiler has every right to believe that whatever this code is trying to do it must be wrong.
Perhaps I was wondering initially, your intention was to dereference the pointer. This is the reason for your compilation error, in any case. If your intention was to, truly, dereference this pointer, then this would've been a simple matter of changing this to
size = *get<1>(rd_rec_size_result);
However, that's not going to be the end of your troubles. Even after this compilation error is fixed, this way, the shown code will still be badly, badly broken.
This is because m_read_generic_t returns a pointer to a local object, which will get destroyed when the function returns, and attempting to dereference this pointer, here, will make demons fly out of your nose.
The real fix here is to change m_read_generic_t to not return a pointer as the 2nd value in the tuple in the first place, thus eliminating the compilation error in the first place.

C++; How to write to an Vect3b pointer of opencv in a function

I have a small problem. I am having a function using a function with 2 Mat pointer objects given, but im having trouble writing to outImg channels to update the img.
void convolve5(Mat *inputImg, Mat *outImg, int *kernel5) {
int channelvaluepixel = inputImg->at<Vect3b>(x,y)[channel];
// loads of changes happening here
outImg->at<Vect3b>(x,y)[0] = channelvaluepixel;
}
Since outImg is a pointer i cannot point to its adress to change it, so i tried this to change the value within the pointer:
*outImg->at<Vect3b>(x,y)[0] = channelvaluepixel;
But this would not work either since the compiler gives me an:
Error: invalid type argument of unary '*' (have 'unsigned char')
Can somebody help?
You are dereferencing whole expression outImg->at<Vect3b>(x,y)[0] instead of just (*outImg).at<Vect3b>(x,y)[0] = channelvaluepixel;

Why the statement int null = 0, *p = null is illegal?

I'm new to C++ and am trying the learn the concept of pointer. Could someone tell me why the C++ statement below is illegal? It seems to me to be legit but I have been told its illegal.
int null = 0, *p = null;
The C++ standard allows pointers to be assigned the value 0 as a constant.
However, the code:
int null = 0;
int *p = null;
does not set p to the constant 0, it sets it to the value of null, which is an integer variable.
If we generalize a little bit, and put int null = 0; on a line, and int *p = null; in a completely different line, with some code in between. There is nothing saying that the code in between doesn't do null = 4; - however, I don't think that is the main reason for not allowing this, but rather that it is easier to write a compiler that checks "is this the integer constant 0" than "is this named constant of the value zero". What if the constant is from another compile unit (a link-time constant)?
Also, reading 0 is much easier than having 46 different coding standards, each of which uses a different name for null.
Note that even if you make const int null = 0;, it is still not the constant 0 - it's a constant of the same value as 0, but not the same, lexically, as 0.
If you try compiling this code then you should get the following error:
error: cannot initialize a variable of type 'int *' with an lvalue of type 'int'
Essentially what is happening is that you are trying to initialize a pointer with a variable. The only thing that is allowed in C++ is assigning a pointer directly to a zero.
int * p = 0;
Something like the example above would work.
To define a pointer you need to use ampersand sign (&) as a prefix to the object you are passing.
int null = 0, *p = &null;
That is going to fix error: cannot initialize a variable of type 'int *' with an value of type 'int'

Wrong use of typedef of typedef(?)

I have problem with code from book:
const int SQUARE_ARRAY_SIZE = 4;
const int SQUARE_INFO_SIZE = 4;
typedef Square SquareArray[SQUARE_ARRAY_SIZE];
typedef SquareArray SquareInfo[SQUARE_INFO_SIZE];
SquareArray RedGeneric = { Square(0, 0), Square(0, 1),
Square(1, 1), Square(1, 0) };
SquareInfo RedInfo = { &RedGeneric, &RedGeneric, \\problem here
&RedGeneric, &RedGeneric };
It yells:
error C2440: 'initializing' : cannot convert from 'SquareArray (*)' to 'Square'
IntelliSense: no suitable constructor exists to convert from "SquareArray *" to "Square"
As I understand SquareInfo stands for array of SquareArray but it seems like vs2013 wants to break it to Squares and as result
SquareInfo m_squareInfo; ...
SquareArray* pSquareArray = m_squareInfo[m_iDirection];
yells:
IntelliSense: a value of type "const Square *" cannot be used to initialize an entity of type "SquareArray *"
Book is from 2008 and I don't know if it worked back then or there is error from beginning. As for q please tell me what's really wrong and how to make it work.
I'm fairly sure that the book meant to write
typedef SquareArray* SquareInfo[SQUARE_INFO_SIZE];
// ^
i.e., SquareInfo is an array of pointers to SquareArrays, rather than an array of SquareArrays. This is consistent with initializations using &RedGeneric and SquareArray* pSquareArray = m_squareInfo[m_iDirection];.
Looks like your book has a typo on that line
typedef SquareArray SquareInfo[SQUARE_INFO_SIZE];
When I make this to be a pointer
typedef SquareArray* SquareInfo[SQUARE_INFO_SIZE];
// ^
the code compiles fine.

Error 23 error C2440: 'return' : cannot convert from 'char [128]' to 'char (&&)[128]'

Basically, I wrote the signature of a method that returns a vector of char and I am getting this error
Error 23 error C2440: 'return' : cannot convert from 'char [128]' to 'char (&&)[128]'
Here is the signature of the method
vector<char[256]>returnMessage(string ACK)
{
}
Also, I can't declare a vector of char as a global variable.
When I do this:
std::vector<char[256]> myvector;
I get:
Error 24 error C1903: unable to recover from previous error(s); stopping compilation
and
Error 23 error C2075: 'Target of operator new()' : array initialization needs curly braces
You have a problem with instantiation, but not declaring type. Just use:
struct Chars256 {
char arr[256];
};
And you will be able to:
vector<Chars256> returnMessage(string ACK) {
Chars256 arr;
Chars256 arr2 = {{0}}; // setting value only for first element, all other will be zeros!
// ...
}
You receive such errors because of internal code of vector. Template substitution fails.
First error is connected to move semantics. Vector tries to move char[256] and fails.
Second with new means that somewhere in code of vector there is new T() and when T is plain array type substitution fails again.
Solution is to use char*