"invalid operands of types ‘float Point3d::*’ and ‘float Point3d::*’ to binary ‘operator<’"
2014-08-19 19:43
609 查看
compare a pointer to member?
up vote2down vote favorite | I was confused about why can't compare pointers to member using binary operator<class Point3d{ protected: //.. public: float x; static list<Point3d*> *freeList; public: float y; static const int chunkSize = 250; public: float z; }; and a template: template< class class_type, class data_type1, class data_type2 > char* access_order(data_type1 class_type:: *mem1, data_type2 class_type:: *mem2) { return mem1 < mem2 ? "member 1 accurs first": "member 2 accurs first"; } when I called the access_order like below: access_order(&Point3d::z, &Point3d::y); the g++ reported: "invalid operands of types ‘float Point3d::*’ and ‘float Point3d::*’ to binary ‘operator<’" |
0 down vote | Pointers to members do not point to some memory themselves. They are just labels. The only thing you can do with them is to convert them to reference to pointee value of the given object with operator.*or ->*or store in another pointer to member variable. struct A { int a; float b; }; A a; int A::* p2m = &A::a; int A::* p2m2 = p2m; int & realPointer = a.*p2m; Note, that you only can compare pointers of the same type, so you can't compare pointer to A::a( int A::*) with pointer to A::b( float A::*)、 |
0 down vote | You can compare the addresses of the members of an object:A a; if (std::less<void*>()(&a.a, &a.b)) std::cout << "a precedes b\n"; else std::cout << "a follows b\n"; |
1 down vote | While it's true that the a null pointer of type "pointer to member of a given type" must be different from any non-null value of that type, offsetting non-null pointers by one is not the only way that a compiler can ensure this. For example, my compiler uses a non-zero representation of null pointer-to-members. namespace { struct a { int x, y; }; } #include <iostream> int main() { int a::*p = &a::x, a::*q = &a::y, a::*r = nullptr; std::cout << "sizeof(int a::*) = " << sizeof(int a::*) << ", sizeof(unsigned long) = " << sizeof(long); std::cout << "\n&a::x = " << *reinterpret_cast<long*>(&p) << "\n&a::y = " << *reinterpret_cast<long*>(&q) << "\nnullptr = " << *reinterpret_cast<long*>(&r) << '\n'; } Produces the following output: sizeof(int a::*) = 8, sizeof(unsigned long) = 8 &a::x = 0 &a::y = 4 nullptr = -1 Your compiler is probably doing something similar, if not identical. This scheme is probably more efficient for most 'normal' use cases for the implementation because it won't have to do an extra "subtract 1" every time you use a non-null pointer-to-member. |
registration required.
C++: Pointer to data member address doubt
up vote5down vote favorite 2 | I have read(Inside C++ object model) that address of pointer to data member in C++ is the offset of data member plus 1? I am trying this on VC++ 2005 but i am not getting exact offset values. For example: Class X{ public: int a; int b; int c; } void x(){ printf("Offsets of a=%d, b=%d, c=%d",&X::a,&X::b,&X::c); } Should print Offsets of a=1, b=5, c=9. But in VC++ 2005 it is coming out to be a=0,b=4,c=8. I am not able to understand this behavior. Excerpt from book: "That expectation, however, is off by one—a somewhat traditional error for both C and C++ programmers. The physical offset of the three coordinate members within the class layout are, respectively, either 0, 4, and 8 if the vptr is placed at the end or 4, 8, and 12 if the vptr is placed at the start of the class. The value returned from taking the member's address, however, is always bumped up by 1. Thus the actual values are 1, 5, and 9, and so on. The problem is distinguishing between a pointer to no data member and a pointer to the first data member. Consider for example: float Point3d::*p1 = 0; float Point3d::*p2 = &Point3d::x; // oops: how to distinguish? if ( p1 == p2 ) { cout << " p1 & p2 contain the same value — "; cout << " they must address the same member!" << endl; } To distinguish between p1 and p2, each actual member offset value is bumped up by 1. Hence, both the compiler (and the user) must remember to subtract 1 before actually using the value to address a member." |
void test() { using namespace std; int X::* pm = NULL; cout << "NULL pointer to member: " << " value = " << pm << ", raw byte value = 0x" << hex << *(unsigned int*)&pm << endl; pm = &X::a; cout << "pointer to member a: " << " value = " << pm << ", raw byte value = 0x" << hex << *(unsigned int*)&pm << endl; pm = &X::b; cout << "pointer to member b: " << " value = " << pm << ", raw byte value = 0x" << hex << *(unsigned int*)&pm << endl; }
On Visual Studio 2008 I get:
NULL pointer to member: value = 0, raw byte value = 0xffffffff pointer to member a: value = 1, raw byte value = 0x0 pointer to member b: value = 1, raw byte value = 0x4
So indeed, this particular compiler is using a special bit pattern to represent a NULL pointer and thus leaving an 0x0 bit pattern as representing a pointer to the first member of an object.
This also means that wherever the compiler generates code to translate such a pointer to an integer or a boolean, it must be taking care to look for that special bit pattern. Thus something like
if(pm)or the conversion performed by the
<<
stream operator is actually written by the compiler as a test against the 0xffffffff bit pattern (instead of how we typically like to think of pointer tests being a raw test against address 0x0).
相关文章推荐
- error: invalid operands of types ‘double’ and ‘double’ to binary ‘operator^’
- error: invalid operands of types 'int()' and 'int' to binary 'operator%'
- 自定义std::sort的比较函数时发生"invalid operator<"错误原因
- 关于"The value for the useBean class attribute is invalid" 错误<转>
- "Android SDK and AVD Manager" cannot be made visible because all of its children are in unavailable
- 6410_io_drv.c: error: invalid operands to binary << (have 'char *' and 'int') 错误处理
- SICP Combine operands of different types
- """select * from TRACEUSER where STARTIME >=#2008-8-8 8:00:00# and STARTIME <= #2008-9-3 15:25:42#"""""
- the error: no operator << matches these operands
- 某些容易产生"invalid operator <"的情况
- "Android SDK and AVD Manager" cannot be made visible because all of its children are in unavailable
- Misleading error message in PowerShell script: "Invalid assignment expression. The left hand side of an assignment operator need
- Invalid configuation file. File "**********" was created by a VMware product with more feature than this version of VMware Workstation and cannot be
- Android开发中遇到的问题(五)——Eclipse导入Android项目出现"Invalid project description overlaps the location of another project"错误的解决办法
- "WARNING: Increasing RAM size to 1GB" and "Cannot set up guest memory 'xxx.ram': Invalid argument".
- Error 1 Operator '+' cannot be applied to operands of type 'string' and 'method group'
- "Sum of Two Integers" and "Sort Colors"
- "Error: ANDROID_HOME is not set and "android" command not in your PATH. You must fulfill at least one of these conditions.".
- "SQL Server does not handle comparison of NText, Text, Xml, or Image data types."
- ")syntax error: invalid arithmetic operator (error token is "