When I compile under g++ I get the following errors:
In function 'int search(int, int, int)':
1584:error: no match for 'operator=' in '* tt = & core.<anonymous union>::tt[((hash_stack[ply] >> 16) & 2047ul)]'
1584:error: note: candidate is:
118:note: tt_type& tt_type::operator=(const tt_type&)
118:note: no known conversion for argument 1 from 'tt_type*' to 'const tt_type&'
static int search(int depth, int alpha, int beta) {
int best_score = -INF;
int best_move = 0;
int score;
struct move *moves;
int incheck = 0;
struct tt_type *tt; //LINE 1584
int oldalpha = alpha;
int oldbeta = beta;
int i, count=0;
nodes++;
/* test for draw by repetition */
hash_stack[ply] = compute_hash();
for (i=ply-4; i>=board[LAST]; i-=2) {
if (hash_stack[i] == hash_stack[ply]) count++;
if (count>=2) return 0;
}
/*
* check transposition table
*/
*tt = &TTABLE[ ((hash_stack[ply]>>16) & (CORE-1)) ];
if (tt->hash == (hash_stack[ply] & 0xffffU)) {
if (tt->depth >= depth) {
if (tt->flag >= 0) alpha = MAX(alpha, tt->score);
if (tt->flag <= 0) beta = MIN(beta, tt->score);
if (alpha >= beta) return tt->score;
}
best_move = tt->move & 07777;
}
Where I have previously defined
struct tt_type { //LINE 118
unsigned short hash; /* - Identifies position */
short move; /* - Best recorded move */
short score; /* - Score */
char flag; /* - How to interpret score */
char depth; /* - Remaining search depth */
};
The most important line in the error message is this:
118:note: no known conversion for argument 1 from 'tt_type*' to 'const tt_type&'
It essentially means that you are trying to assign a pointer to the reference.
Which in turn makes me think that changing * tt = & core.::tt[((hash_stack[ply] >> 16) & 2047ul)] in your code to * tt = core.::tt[((hash_stack[ply] >> 16) & 2047ul)] for deep copy or to tt = & core.::tt[((hash_stack[ply] >> 16) & 2047ul)] for shallow copy will solve the problem (depending on your perspective).
I suspect that your line 1584 is really this one:
*tt = &TTABLE[ ((hash_stack[ply]>>16) & (CORE-1)) ];
*tt is of type struct tt_type. The RHS is of the form &..., so it's of some pointer type. You can assign a struct to a struct, or a pointer to a pointer, but you can't assign a pointer value to a struct (unless you've overloaded the assignment operator).
I haven't studied the code enough to understand it, but you probably want to change *tt = ... to tt = ....
*tt = &TTABLE[ ((hash_stack[ply]>>16) & (CORE-1)) ];
You're trying to store a pointer into a variable that's not a pointer.
You need either
*tt = TTABLE[ ((hash_stack[ply]>>16) & (CORE-1)) ];
to make a copy of one element of the array (this isn't going to work, since tt is not initialized)
or
tt = &TTABLE[ ((hash_stack[ply]>>16) & (CORE-1)) ];
to make a pointer into the array.
Another way of writing the second version is
tt = TTABLE + ((hash_stack[ply]>>16) & (CORE-1));
In this line:
*tt = &TTABLE[ ((hash_stack[ply]>>16) & (CORE-1)) ];
You're trying to assign a variable of type tt_type to another thing of some other type. I don't know what TTABLE is, but as a wild guess, try removing the & (the & would cause an error if TTABLE is an array of tt_types. You'd be trying to assign a tt_type* to a tt_type).
*tt = &TTABLE[/**/];
You're assigning your struct from a pointer. As clarified by no known conversion for argument 1 from'tt_type*' to 'const tt_type&' It cannot convert the tt_type* to a tt_type& to make the copy.
I don't know what TTABLE is, but I'd remove the & from it.
Related
This question already has answers here:
Pointer to class data member "::*"
(18 answers)
Closed 3 months ago.
i took the below code from a different question on stackoverflow, im not sure What do the lines int (Foo :: * ptr); and int (Foo :: * ptr) (); mean? Can anyone share some answers?
struct Foo {
int a;
int b;
};
int main ()
{
Foo foo;
int (Foo :: * ptr);
ptr = & Foo :: a;
foo .*ptr = 123; // foo.a = 123;
ptr = & Foo :: b;
foo .*ptr = 234; // foo.b = 234;
}
Member functions are almost the same.
struct Foo {
int a ();
int b ();
};
int main ()
{
Foo foo;
int (Foo :: * ptr) ();
ptr = & Foo :: a;
(foo .*ptr) (); // foo.a ();
ptr = & Foo :: b;
(foo .*ptr) (); // foo.b ();
}
Debugging to no avail
Pointer to members is a long story to tell. First we assume that you've known what a normal pointer is.
Pointer to members suggests that it can point to the specific member of any instance of class. There are two types of pointer to members, first to member variables and second to member functions.
Before that, the variables and functions can be static or non-static. For static ones, it's no other than normal global ones from the program's perspective, e.g. in Linux ELF, static data are stored in .data directly, where the global variables are also stored. From the angle of the programmers, they are just accessing a special global function / variable as well, just adding some Class::. So, the pointer to static member variable / function is just the same as the pointer to a normal variable / function.
Now let's talk about the non-static ones. Non-static members should always bind to some specific object, e.g. obj.a or obj.func() and Class::a or Class::func() is illegal. Then, is it possible to use a pointer to suggest that "I hope to point to a specific member of any instance, and when I want to use it, I will bind an instance"? That's what the pointer to members do.
Wait... you may think: "That bothers! Why can't I just use the .?". To maintain the consistency, we will go back to this question finally. Now we assume it's useful first, and see what syntax it uses.
class ClassOpTest
{
public:
int nsVar; // non-static variable.
void nsFunc(int){return;} // non-static function.
};
int ClassOpTest::* nsVarPtr = &ClassOpTest::nsVar;
void (ClassOpTest::*nsFuncPtr)(int) = &ClassOpTest::nsFunc;
int main()
{
ClassOpTest object2;
ClassOpTest* object2Ptr = &object2;
object.*nsVarPtr = 1; // equals to object.nsVar = 1;
object2.*nsVarPtr = 2; // equals to object2.nsVar = 2;
object2Ptr->*nsVarPtr = 3; // equals to object2.nsVar = 3;
// Note that these paratheses are necessary, considering the operation order.
// If there are not, nsFuncPtr() will be resolved first rather than object.*nsFuncPtr().
// That is, the compiler will regard the nsFuncPtr as a normal function (pointer)
// rather than pointer to member function, so "obj.*" is just a meaningless mess.
// All in all, no paratheses will cause compilation error.
(object.*nsFuncPtr)(1); // equals to object.nsFunc(1);
(object2Ptr->*nsFuncPtr)(2); // equals to object2.nsFunc(2);
return 0;
}
You may find it's troublesome to write types like this, so you can use deduced type in C++11 as:
using ClassOpTestIntPtr = decltype(&ClassOpTest::nsVar);
using ClassOpTestFuncPtr = decltype(&ClassOpTest::nsFunc);
ClassOpTestIntPtr nsVarPtr = &ClassOpTest::nsVar;
ClassOpTestFuncPtr nsFuncPtr = &ClassOpTest::nsFunc;
Notice that the decltype doesn't mean it always points to nsVar or nsFunc; it means the type same as them.
You may also think .* or ->* is oblique(me too!), then you can use std::invoke in C++17 like this :
std::invoke(nsVarPtr, object2) = 1; // equals to object.*nsVarPtr = 1;
std::invoke(nsVarPtr, &object2) = 2; // equals to object2Ptr->*nsVarPtr = 2;
// both work.
std::invoke(nsFuncPtr, object2, 1); // equals to (object.*nsFunc)(1);
std::invoke(nsFuncPtr, &object2, 2); // equals to (object2Ptr->*nsFunc)(2);
std::invoke is significantly useful, but that's not the point of the answer. In a nutshell, it will use corresponding operator when the second calling parameter varies.
Finally, why is it useful? In my point of view, that's mostly because the pointer only conveys the type, and the type may infer lots of members. For instance:
struct RGB
{
std::uint8_t r;
std::uint8_t g;
std::uint8_t b;
};
and I hope to blend two std::vector<RGB> using Intel's SIMD intrinsics. First for r, that is:
reg1 = _mm_set_epi16(RGBdata1[i + 7].r, RGBdata1[i + 6].r, RGBdata1[i + 5].r,
RGBdata1[i + 4].r, RGBdata1[i + 3].r, RGBdata1[i + 2].r,
RGBdata1[i + 1].r, RGBdata1[i].r);
reg2 = _mm_set_epi16(RGBdata2[i + 7].r, RGBdata2[i + 6].r, RGBdata2[i + 5].r,
RGBdata2[i + 4].r, RGBdata2[i + 3].r, RGBdata2[i + 2].r,
RGBdata2[i + 1].r, RGBdata2[i].r);
reg1 = _mm_mullo_epi16(reg1, alphaReg1);
reg2 = _mm_mullo_epi16(reg2, alphaReg2);
resultReg1 = _mm_add_epi16(reg1, reg2);
// for simplicity, code below omitted; there are also manys operation to get the result.
// ...
// store back
_mm_store_si128((__m128i*)buffer, resultReg1);
for(int k = 0; k < 16; k++)
{
outRGBdata[i + k].r = buffer[k];
}
So what about g and b? Oops, okay, you have to paste the code twice. What if you find some bugs and want to change something? You have to paste again for g and b. That suffers! If we use pointer to members, then :
using RGBColorPtr = std::uint8_t RGB::*;
void SIMDBlendColor(RGB* begin1, RGB* begin2,
RGB* outBegin, RGBColorPtr color,
__m128i alphaReg1, __m128i alphaReg2)
{
__m128i resultReg1, reg1, reg2;
alignas(16) std::uint8_t buffer[16];
reg1 = _mm_set_epi16((begin1 + 7)->*color, (begin1 + 6)->*color,
(begin1 + 5)->*color, (begin1 + 4)->*color,
(begin1 + 3)->*color, (begin1 + 2)->*color,
(begin1 + 1)->*color, begin1->*color);
reg2 = _mm_set_epi16((begin2 + 7)->*color, (begin2 + 6)->*color,
(begin2 + 5)->*color, (begin2 + 4)->*color,
(begin2 + 3)->*color, (begin2 + 2)->*color,
(begin2 + 1)->*color, begin2->*color);
reg1 = _mm_mullo_epi16(reg1, alphaReg1);
reg2 = _mm_mullo_epi16(reg2, alphaReg2);
resultReg1 = _mm_add_epi16(reg1, reg2);
// ...
_mm_store_si128((__m128i*)buffer, resultReg1);
for(int k = 0; k < 16; k++)
{
(outBegin + k)->*color = buffer[k];
}
return;
}
Then, you can just call like this :
SIMDBlendColor(RGBdata1.data() + i, RGBdata2.data() + i, outRGBdata.data() + i, &RGB::r, alphaReg1, alphaReg2);
SIMDBlendColor(RGBdata1.data() + i, RGBdata2.data() + i, outRGBdata.data() + i, &RGB::g, alphaReg1, alphaReg2);
SIMDBlendColor(RGBdata1.data() + i, RGBdata2.data() + i, outRGBdata.data() + i, &RGB::b, alphaReg1, alphaReg2);
Clean and beautiful!
BTW, I strongly recommend you to check iso-cpp-wiki for more information.
I need to create an array of pointers of different types. Some variables are defined at the beginning and their vectors are assigned to different spaces in the array. Later, from another process, the values of these variables can be changed using the pointers stored in the array. Variables are accessed directly from the main process (without pointers)
In de main process at start:
void *values[255];
uint8_t val1 = 12;
uint16_t val2 = 3478;
SetIDVariable(&val1, 0);
SetIDVariable(&val2, 2);
Others functions:
void SetIDVariable(uint8_t *variable, uint8_t id) {
values[id] = variable;
}
void SetIDVariable(uint16_t *variable, uint8_t id) {
values[id] = variable;
}
In other process (x is a any number for check if value change):
values[0] = (void*)(val1 + x);
values[2] = (void*)(val2 + x);
In main process:
Serial.print("Value 1: "); Serial.println(val1);
Serial.print("Value 2: "); Serial.println(val2);
Values are always 12 and 3478. Any ideas?
You are converting an integer value to pointer. Maybe you wanted to do this:
*((uint8_t *) values[0]) = (*((uint8_t *) values[0])+x);
*((uint16_t *) values[2]) = (*((uint16_t *) values[2])+x);
also see these questions: this question and this question
You not change val1 and val2 with this code. You just affect new pointer allocation in values
values[0] = (void*)(val1 + x);
values[2] = (void*)(val2 + x);
I'm trying to have my function return 3 values (n, down and across) I've read online how 'auto' can be used but must be doing something wrong.
The function takes in a 2D vector of integers (as well as other variables) and checks for how many numbers are connected to board[0][0] such that they are the same number.
I've tried putting auto in front of the function inside the function itself, tried leaving it blank, tried just having chain = chainNodes(...) but I always seem to get an error. Here's the code:
tuple<int, int, int> chainNodes(vector<vector<int>> board, int originalNum,
unsigned int across, unsigned int down, int ijSum,
int n)
{
struct chain {
int n, down, across;
};
if(down + across > ijSum) {
ijSum = down + across;
} else if((down + across == ijSum) &&
((down - across) * (down - across) < (ijSum) * (ijSum))) {
ijSum = down + across;
}
board[down][across] = 0;
n += 1;
// Check below
if((down != (board.size() - 1)) && (board[down + 1][across]) == originalNum) {
down += 1;
auto [n, iPoint, jPoint] = chainNodes(board, originalNum, across, down, ijSum, n);
down -= 1;
}
// Check right, up and left (I've removed so its not too messy here)
return chain{n, down, across};
}
Sorry, I forgot to include the error message.
error: use of 'n' before deduction of 'auto'
It occurs on the line that uses auto.
Issue with
auto [n, iPoint, jPoint] = chainNodes(board, originalNum, across, down, ijSum, n);
is similar to
auto n = foo(n); // `foo(n)` uses `n` from `auto n`,
// not the one from outer scope as function parameter
The construct int a = a + 1; is legal but lead to UB as reading uninitialized variable.
That kind of construct allows legal and valid behavior void* p = &p;.
Your code has other errors and it is not clear for me expected behavior of the function.
So not sure if following is the correct fix, but you might want:
n = std::get<0>(chainNodes(board, originalNum, across, down, ijSum, n));
when i trying make function to set meshes, then i got error E0137. getMeshes works well.
When i trying to do somethink like
RpMesh* a = header->GetMeshes();
a = newMeshes;
this too not working.
struct RpMeshHeader
{
unsigned int flags;
unsigned short numMeshes;
unsigned short serialNum;
unsigned int totalIndicesInMesh;
unsigned int firstMeshOffset;
RpMesh *getMeshes(void) { return (RpMesh*)(this + 1); }
void setMeshes(RpMesh* newMesh)
{
(RpMesh*)(this + 1)= newMesh;
}
bool isValidMeshId(int meshId)
{
return (meshId != NULL && numMeshes >= meshId);
}
}
Whole file
https://github.com/CrosRoad95/mtasa-blue/blob/f740b0d7410f33ff323cad25bf897725ad44d7d3/Client/sdk/game/RenderWare.h
The error here is quite clear:
void setMeshes(RpMesh* newMesh)
{
(RpMesh*)(this + 1)= newMesh;
}
error: lvalue required as left operand of assignment
the following is not an lvalue and so you cannot assign to it.
(RpMesh*)(this + 1)
The github you linked shows the setMeshes as the following
void setMeshes(RpMesh* newMeshes)
{
RpMesh* meshes = (RpMesh*)(this + 1);
meshes = newMeshes;
}
which is fine in terms of syntax. First you create a pointer meshes to which you assign the address of (this+1) (if this was an array, this+1 would point to the next element in the array) but with a cast!
You cast this hypothetical next element in this array of RpMeashHeader to RpMesh with a C-style cast (which afaik will default to a reinterpret_cast in this case see here for more information)
But has this memory every been allocated? This seems unsafe.
So, been building this class:
public class BitArray {
public:
unsigned char* Data;
UInt64 BitLen;
UInt64 ByteLen;
private:
void SetLen(UInt64 BitLen) {
this->BitLen = BitLen;
ByteLen = (BitLen + 7) / 8;
Data = new unsigned char(ByteLen + 1);
Data[ByteLen] = 0;
}
public:
BitArray(UInt64 BitLen) {
SetLen(BitLen);
}
BitArray(unsigned char* Data, UInt64 BitLen) {
SetLen(BitLen);
memcpy(this->Data, Data, ByteLen);
}
unsigned char GetByte(UInt64 BitStart) {
UInt64 ByteStart = BitStart / 8;
unsigned char BitsLow = (BitStart - ByteStart * 8);
unsigned char BitsHigh = 8 - BitsLow;
unsigned char high = (Data[ByteStart] & ((1 << BitsHigh) - 1)) << BitsLow;
unsigned char low = (Data[ByteStart + 1] >> BitsHigh) & ((1 << BitsLow) - 1);
return high | low;
}
BitArray* SubArray(UInt64 BitStart, UInt64 BitLen) {
BitArray* ret = new BitArray(BitLen);
UInt64 rc = 0;
for (UInt64 i = BitStart; i < BitLen; i += 8) {
ret->Data[rc] = GetByte(i);
rc++;
}
Data[rc - 1] ^= (1 << (BitLen - ret->ByteLen * 8)) - 1;
return ret;
}
};
just finished writing the SubArray function and went on to test but I get "Access violation: attempted to read protected memory" on the line where GetByte(i) gets called. I tested a bit and it doesn't seem to have anything to do with the data array or i, placing "int derp = GetByte(0)" on the first line of the function produces the same error.
calling GetByte from outside the class works fine, I don't understand whats going on.
the test function looks like this:
unsigned char test[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
BitArray* juku = new BitArray(test, 64);
auto banana = juku->GetByte(7); //this works fine
auto pie = juku->SubArray(7, 8);
You might want to consider creating an array of characters, changing:
Data = new unsigned char(ByteLen + 1);
into:
Data = new unsigned char[ByteLen + 1];
In the former, the value inside the parentheses is not the desired length, it's the value that *Data gets initialised to. If you use 65 (in an ASCII system), the first character becomes A.
Having said that, C++ already has a pretty efficient std::bitset for exactly the situation you seem to be in. If your intent is to learn how to make classes, by all means write your own. However, if you want to just make your life simple, you may want to consider using the facilities already provided rather than rolling your own.