How can member functions compare with each other?

I would like to know if I can compare 2 member functions with the "<" operator. I can do "==", but I cannot use it in the example below. I tried to make them void * , but that won't work either.

template <class Receiver, class Sender> class CallBack2 : public ICallBack2 { protected: Receiver* receiver; void(Receiver::*function)(Sender*); Sender* sender; public: CallBack2(Receiver* _receiver, void(Receiver::*_function)(Sender*), Sender* _sender) : receiver(_receiver), function(_function), sender(_sender) {}; virtual ~CallBack2() {}; virtual void callBack() { (receiver->*function)(sender); } virtual bool operator<(const ICallBack2* _other) const { CallBack2<Receiver, Sender>* other = (CallBack2<Receiver, Sender>*)_other; if (receiver < other->receiver) { return true; } else if (receiver == other->receiver && function < other->function) { return true; // this line gives the error } return false; } }; 

Any ideas please?

+1
source share
7 answers

If you just want to randomly order them as keys in a set / map, you can reinterpret_cast them. You may need a template class, for example exact_int<sizeof(void (Foo::*bar)())>::type , because pointers to member functions can be funny in size .

+1
source

C ++ 03 § 5.9 , which covers the semantics of the embedded <,>, <= and> =, does not mention pointers to members and states:

No other pointer comparisons are specified.

According to § 8.3.3 , 3

The type "pointer to element" is different from the type "pointer",

As a result, we can conclude the result of relational operators applied to pointers to members (regardless of whether functions or fields) are undefined.

Please note that “unspecified behavior” is different from “undefined behavior”, but it does mean that you cannot use the operators with benefit, as different implementations may have different results. "Unspecified" basically means that the implementation gets a definition of behavior.

+3
source

5.9.7 (relational operators): "No other pointer comparisons specified."

Since 5.9 is unclear (it concerns functions, but not explicitly member functions), a quick look at 5.10 (equality comparison) clearly separates functions from member functions:

In addition, you can compare pointers to elements or a pointer to a member and a null pointer constant. The conversion of pointers to members (4.11) and qualification conversions (4.4) are performed to bring them to a common type. If one operand is a null pointer constant, the generic type is the type of the other operand. Otherwise, type is a pointer to a member type similar to (4.4) the type of one of the operands with the cv-qualification signature (4.4), which is the union of the cv-qualification signatures of operand types. [Note: this means that any pointer to an element can be compared to a null pointer constant. ] If both operands are equal to zero, they are compared equal. Otherwise, if only one of them is equal to zero, they are compared unevenly. Otherwise, if either is a pointer to a virtual member function, the result is undefined. Otherwise, they compare equal ones if and only if they belong to the same member of the same derived object (1.8) or the same subobject if they were dereferenced by a hypothetical object with a related class type.

Thus, you can use operators, the value == and != specified, but the value < , > , <= and >= not specified.

In particular, nothing provides transitivity, so it is unclear whether they are inserted correctly into the set.

+1
source

Although the description gets a little long, how about having a dummy variable and comparing its pointer as follows:

 template< class T > struct comparable_value { T value; char *id; comparable_value( T value, char* id ) : value( value ), id( id ) {} bool operator<( comparable_value const& x ) const { return std::less< char* >()( id, x.id ); } }; template< class T, TV > comparable_value< T > get_comparable_value() { static char dummy; return comparable_value< T >( V, &dummy ); } struct A { void f() { puts( "f" ); } void g() { puts( "g" ); } }; int main() { typedef void (A::*MF)(); typedef std::set< comparable_value< MF > > set_t; set_t s; s.insert( get_comparable_value< MF, &A::f >() ); s.insert( get_comparable_value< MF, &A::g >() ); A a; for ( set_t::iterator i = s.begin(), e = s.end(); i != e; ++ i ) (a.*i->value)(); } 

Here is the ideone test.

+1
source

You could do something like Ise's idea, but save it only in the Callback2 class so that you don't have to change anything using the class.

 template <class Receiver, class Sender>class CallBack2 : public ICallBack2 { private: static int nextSequenceNumber; int sequenceNumber; //snip public: CallBack2(Receiver* _receiver, void(Receiver::*_function)(Sender*), Sender* _sender) : sequenceNumber(nextSequenceNumber++), receiver(_receiver), function(_function), sender(_sender) {}; //snip virtual bool operator<(const ICallBack2* _other) const { return sequenceNumber<_other->sequenceNumber;} 
0
source

Taking the address of a member function leads to a constant expression that cannot be stored in a variable. It can be used only for comparison to be equal to another expression that represents the address of a function that takes the same set of parameters, with the same return type and the same type of this pointer.

  class a { public: virtual void test(); }; class b { public: virtual void test(); }; .... a *pa = new a; b *pb = new b; if (pb->test == pa->test) // legal, but false if (pb->test==pb::test) // legal and true // pa->test will evaluate to a::test, although calling pa->test() would call // b::test() 
-one
source

It makes no sense to compare two function pointers. What you could compare is actually the return value of these functions:

 *function(sender) < *(other->function)(sender) 

but in your case you declare the function as:

 void(Receiver::*function)(Sender*); 

so in my opinion. Comparing functions is useless. Either replace the function signature to return something, or better describe your business scenario so that we can better understand what you want.

-one
source

Source: https://habr.com/ru/post/1395476/


All Articles