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<’"
Is there a way compare pointer to member, I mean the unequal comparison, and how?
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";
One of the best option - make a raw copy via std::memcpy
, calculate hash and then use it for comparison (thanks @HolyBlackCat for comments). The function below calculates the hash for passed pointer-to-member (tested on modern C++ 17 compilers VS, GCC. CLang).
#include <cstring>
#include <string_view>
#include <functional>
template <typename TObject, typename TMember>
size_t HashMemberPtr(TMember TObject::* memberPtr)
{
char buf[sizeof memberPtr];
std::memcpy(&buf, &memberPtr, sizeof memberPtr);
return std::hash<std::string_view>{}(std::string_view(buf, sizeof buf));
}
Unfortunately it's not compatible with std::hash<>
as last requires only one template argument.
How to use:
struct CPoint3D
{
float x;
float y;
float z;
};
int main()
{
const size_t xHash = HashMemberPtr(&CPoint3D::x);
assert(xHash == HashMemberPtr(&CPoint3D::x));
assert(xHash != HashMemberPtr(&CPoint3D::y));
assert(xHash != HashMemberPtr(&CPoint3D::z));
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With