|
still getting the exception if the key to the map is a structure
consisting of a char[4] and 2 int how would I set < operator
the only way I got it to work
was by return int1 < x.int1
what would like to do
is concatenate all of them in 12 bytes and compare 12 bytes against 12 bytes
thanks
|
|
|
|
|
Since my data was 12 bytes long I was lucky there happened to be a data type 16 bytes long a "long double" I just filled the first 4 bytes with zeros and
;
struct usingrange
{
ESDID esdid;
int start;
int end;
usingrange() { start = 0; end = 0; return; }
bool operator<(const usingrange& x) const {
union
{
long double a;
char str1[16];
}c;
union
{
long double b;
char str2[16];
}d;
::memset(&c.str1, 0x00, 16);
::memset(&d.str2, 0x00, 16);
::memcpy(&c.str1[4], &esdid, 4);
::memcpy(&c.str1[8],&start,4);
::memcpy(&c.str1[12], &end, 4);
::memcpy(&d.str2[4], &x.esdid, 4);
::memcpy(&d.str2[8], &x.start, 4);
::memcpy(&d.str2[12], &x.end, 4);
return c.a < d.b;
}
};
|
|
|
|
|
That has a couple of issues. Firstly, you are invoking undefined behavior: Union declaration - cppreference.com
Secondly, you're expecting that the bit patterns of 2 doubles can be compared. This may not be the case, as you may a NaN this way, and then any comparison will return false:
[k5054@localhost tmp]$ cat example.c
int main()
{
double d = 0.0 / 0.0; // produces NaN
printf("1.0 < d = %d\n", 1.0 < d);
printf("d < 1.0 = %d\n", d < 1.0);
printf("d == d = %d\n", d == d);
}
[k5054@localhost tmp]$ gcc example.c -o example
[k5054@localhost tmp]$ ./example
1.0 < d = 0
d < 1.0 = 0
d == d = 0
[k5054@localhost tmp]$
As we can see in the above code, NaN compared to anything, even itself returns false.
If all you want to do is compare bits, you might as well just go ahead and use memcmp()
*#35;include <cstring>
struct usingrange {
ESDID esdid;
int start;
int end;
bool operator<(const usingrange& x)const {
return ::memcmp(this, &x, sizeof(*this)
}
}; This relies on the fact that the sizeof a struct or a class is the size of its individual members. This only becomes tricky if your struct/class includes STL or other objects like std::string or std::vector.
Keep Calm and Carry On
|
|
|
|
|
The return using memcmp as operands will get an exception in order to get around this I need to to have to have the syntax return operand1 < operand2 truthfully the order of the items is not that important as long as I am able to retrieve the data by key thanks
|
|
|
|
|
I think you're making it too complicated:
struct ESDID
{
char c[4];
bool operator<(const ESDID& other) const
{
return c[0] < other.c[0] && c[1] < other.c[1] &&
c[2] < other.c[2] && c[3] < other.c[3];
}
}
struct usingrange
{
ESDID esdid;
int start;
int end;
bool operator<(const usingrange& other) const
{
return esdid < other.esdid && start < other.start &&
end < other.end;
}
}
I've used && and < because you do not want operator<() to return true for two different objects when you swap them around.
|
|
|
|
|
just tried it that did it thank you
|
|
|
|
|
hi
I am getting a read access error in xtree line 1607. This after i have inserted 4,527 map entries successfully I did a call to map::maxsize using a unsigned integer and it came up with a number 0x76767676 I dont think memory is the issue as I have 64 gb machine
I bypassed the entry just to see if there was something wrong with that entry and go an error on the next as well
here is the microsoft code I underlined the while statement with the issue intellesense is giving the message _Trnode was 0x40D51F000040.
any guidence who i shoud go about debugging would be appreciated
template <class _Keyty>
_Tree_find_result<_Nodeptr> _Find_lower_bound(const _Keyty& _Keyval) const {
const auto _Scary = _Get_scary();
_Tree_find_result<_Nodeptr> _Result{{_Scary->_Myhead->_Parent, _Tree_child::_Right}, _Scary->_Myhead};
_Nodeptr _Trynode = _Result._Location._Parent;
while (!_Trynode->_Isnil) {
_Result._Location._Parent = _Trynode;
if (_DEBUG_LT_PRED(_Getcomp(), _Traits::_Kfn(_Trynode->_Myval), _Keyval)) {
_Result._Location._Child = _Tree_child::_Right;
_Trynode = _Trynode->_Right;
} else {
_Result._Location._Child = _Tree_child::_Left;
_Result._Bound = _Trynode;
_Trynode = _Trynode->_Left;
}
}
|
|
|
|
|
I had a buffer that was way too small it overlayed data inluding the pointer to the map class
thanks
|
|
|
|
|
Hi
my overloaded operator are in my header so I make a breakpoint watching them being invoked except for the = operator hope some can tell me why
i'll post
first type of struct using range
;
struct usingrange
{
ESDID esdid;
int start;
int end;
uint32_t operator=(const BYTE z[4])
{
return ((z[0] << 24) | (z[1] << 16) | (z[2] << 8) | z[3]);
};
bool operator<(const usingrange x) const {
if (esdid < x.esdid) return esdid < x.esdid;
if (start < x.start) return start < x.start; if (end < x.end) return end < x.end;
};
};
next my code with the = operator the lvalue is member of using range I would think that would casue invocation of my overloaded operator
usingrange using_range{ usingpoint->usingesdid };
using_range.start = (BYTE &)usingpoint->statement;
using_range.end = (BYTE &)usingpoint->laststatement;
|
|
|
|
|
Again, not sure which one of the 3 statements you would expect to invoke the assignment operator. The first one:
usingrange using_range{ usingpoint->usingesdid }; is a declaration that invokes a constructor. As you don't have a constructor, the compiler creates a default one.
The second and the third:
using_range.start = (BYTE &)usingpoint->statement;
using_range.end = (BYTE &)usingpoint->laststatement; are simply integer assignments.
If you would want to invoke the assignment operator you would need to write something like
usingrange using_range2;
using_range2 = using_range;
Mircea
|
|
|
|
|
these two the lvalue is a int and a member of using range the rvalue is of type BYTE [4] ? I am sure I am not understanding something ?
using_range.start = *usingpoint->statement;
using_range.end = *usingpoint->laststatement;
|
|
|
|
|
If statement is BYTE[4] , usingpoint->statement is a pointer to a BYTE value. So *usingpoint->laststatement is the content of the first byte. It can be assigned to an integer without any problem. That's probably not what you want but that's what the compiler understood.
The assignment operator that you defined is for assigning the WHOLE structure. It doesn't apply to individual members.
Mircea
|
|
|
|
|
you are right I saw that in that disassembly however I made a breakpoint at "int operator+..." and it never got invoked probably because as you said the rvalue is BYTE while in the operator= parameter it BYTE z[4]; when I have the code
using_range.start = usingpoint->statement; I got an error message from intellsense saying cannt assign int to BYTE *
|
|
|
|
|
I think you misunderstood the functioning of overloaded operators. I'll try to explain but it's best if you check with a proper manual. I'm not a particularly good teacher
If you have something like:
struct A {
char ch;
long l;
};
struct B {
int i;
char c;
};
A a;
B b;
If you write an assignment:
a = b;
The compiler will complain that it doesn't know how to assign a B to an A. Kind of an apples and oranges problem.
However you can write:
a.l = b.i;
a.ch = b.c; because those are standard types and compiler knows how to perform those assignments without needing a user defined assignment operator.
Now we add a user defined assignment operator:
struct A {
char ch;
long l;
int operator =(B& rhs) {l = rhs.i; ch = rhs.c; return 1;}
};
After that we can write:
a = b; and the compiler will know how to do the assignment.
You can have many such assignment operators. For instance you might add another one to assign an A to another A:
struct A {
char ch;
long l;
int operator =(B& rhs) {l = rhs.i; ch = rhs.c; return 1;}
int operator =(A& rhs) {l = rhs.l; ch = rhs.ch; return 1}
};
The assignment operator that takes an object of the same kind on the right hand side is called "principal assignment operator".
Note however that we cannot "chain" the assignment operator. If we write:
A a1;
a1 = a = b; we will get an error because the result of
a = b is an int and cannot be assigned to an A. To respect the conventions we would have to change the signature of the principal assignment operator:
struct A {
char ch;
long l;
int operator =(const B& rhs) {l = rhs.i; ch = rhs.c; return 1;}
A& operator =(const A& rhs) {l = rhs.l; ch = rhs.ch; return *this;}
};
Note that I also made the right hand side a reference to a const.
I hope you will find useful my little lecture on assignment operators but, again, best would be to check with a real manual.
Mircea
|
|
|
|
|
thanks beginning to see there is not a way to do what I want with operator overloading
|
|
|
|
|
Hi
I am still having problems with map::insert
Here is my data
struct usingx
{
unsigned char rectype;
#define using 0
#define pop 0x20
#define push 0x40
#define drop 0x80
unsigned char usingflag
#define oridinaryusing 0
#define labeledusing 0x10
#define depedentusing 0x20
#define labeldependentusing 0x30
; ESDID locesdid;
BYTE statement[4];
BYTE location[4];
BYTE usingvalue[4];
BYTE laststatement[4];
ESDID usingesdid;
unsigned char registerx;
BYTE displacement[2];
BYTE reservedz;
BYTE usingrange[4];
BYTE reservedu[2];
BYTE labeloffset[4];
BYTE labelength[4];
char* labelx;
};
Here is the key that I am using the start and end variable are big endian so I have to convert it and overloaded the = operator;
struct usingrange
{
ESDID esdid;
int start;
int end;
int operator=(BYTE z[4]) { return _byteswap_ulong((int)z[4]); };
bool operator<(const usingrange x) const {
if (esdid < x.esdid) return esdid < x.esdid;
if (start < x.start) return start < x.start; if (end < x.end) return end < x.end;
};
here is the code using the map::insert
usingrange using_range{ usingpoint->usingesdid };
using_range.start = *usingpoint->statement;
using_range.end = *usingpoint->laststatement;
procpointer->usingptr->insert({ using_range,*usingpoint });
break;
I made breakpoints on the operator= code and thought when I stepped into it with the vs debugger it would trace it but it didnt
both start and end ended up zeros
dont know why ?
|
|
|
|
|
The line
usingrange using_range{ usingpoint->usingesdid };
does not invoke your assignment operator. This is a constructor and it will just copy the argument. Not sure where you expected the assignment to be invoked.
I would replace the assignments with a constructor similar to this:
struct usingrange
{
usingrange(usingx& x) {
esdid = byte_swap(x.usingesdid;
start = x.statement;
end = x.laststatement;
}
ESDID esdid;
int start;
int end;
As a comment, your comparison operator is suboptimal and incomplete. I’m surprised you didn’t get a warning that not all control paths return a value.
Mircea
|
|
|
|
|
I understand at this point I am trying to get the =operator overload working I think it’s only referencing the first byte as opposed to 4 bytes
Thought if I cast it it would work but didn’t going to try to move it to a int
|
|
|
|
|
Message Closed
modified 18-Dec-22 13:49pm.
|
|
|
|
|
You can simplify to:
auto ret = procpointer->extsymcollector->insert({exsympointer->SYMESDID, *exsympointer})
ForNow wrote: my code does NOT complie
What compiler to you use? what message to you get?
Mircea
|
|
|
|
|
That worked with iterator thanks these overloads drive me crazy 🙂
|
|
|
|
|
when I specify a return of a iterator
I get no suitable conversion
map<uint32_t, extsymbol> ::iterator extsymiter;
extsympointer = procpointer->extsymcollector->insert({exsympointer->SYMESDID, * exsympointer });
|
|
|
|
|
std::map::insert returns a pair. Nothing you can do about that.
Your code should look like:
map<uint32_t, extsymbol> ::iterator extsymiter;
auto ret = procpointer->extsymcollector->insert({exsympointer->SYMESDID, * exsympointer });
if (ret.second)
extsymiter = ret.first;
else
If you don't care if the element was there or not, you can just skip the if .
Mircea
|
|
|
|
|
thanks, I tried that
BTW I looked at the value of the iterator in storage and seems it prefixes my data with a int with the value of the entry number
Thank you again
|
|
|
|
|
Hi Mainframe data big endian which I am trying to typedef 4 bytes I would rather not do it as int
I tried the following typedef char ESDID[4] where ESDID would represent 4 bytes
I also have this type ESDID in structure and would like to use it as a key
for example
struct syminfo
{
unsigned char recordtype;
unsigned char recordtypeflag;
ESDID symesdid;
BYTE seclen[4];
ESDID eseclen;
char* symname;
};
I am getting all sort of comple errors when I map it
syminfo* exsympointer = (syminfo*)procpointer->buffer;
procpointer->extsymcollector.insert(std::pair<ESDID, syminfo>(exsympointer->symesdid, *exsympointer));
The map is define as such
map<ESDID, syminfo> extsymcollector;
I think thesee aerror are from the way I tried to typdef ESDID if also tried to set as an struct type
struct ESDID
{
char x[4];
};
either way I get errors
|
|
|
|