I have a class:
class Car
{
public:
Car();
~Car();
// nr indicates which particular door.
void startEngie();
void openDoor(int nr);
void closeDoor(int nr);
void openWindow(int nr);
void closeWindow(int nr);
void turnOnAirConditioner(int vloume);
}
Now by void (Car::*action)(int)
I declare a pointer named action
to Car
method. The problem is that many methods can be assigned to it: &Car::openDoor
, &Car::closeDoor
, &Car::openWindow
, &Car::closeWindow
, &Car::turnOnAirConditioner
, but not &Car::startEngie
.
I wonder if I am right: there is no way to declare a pointer to a particular method only. In other words: pointer type
, which accept only a particular named function, can't be declared.
You can't define a type that is just "one specific value of this other type", for instance a type whose only existing value is exactly &Car::closeDoor
.
One thing you can do is reach for the Swiss army knife of programming - introduce a level of indirection - and define a type that represents one specific value by wrapping it inside something else.
// Simplified Car
class Car
{
public:
void openDoor(int i) { std::cout << "open door\n"; }
void closeWindow(int i) { std:cout << "close window\n"; }
};
using Fun = void (Car::*)(int);
// A template for an immutable structure, so it
// can hold only one specific value; the template argument.
template<Fun fun>
struct CarOperation
{
const Fun f = fun;
};
// Now we can make one type for each operation
using OpenDoor = CarOperation<&Car::openDoor>;
using CloseWindow = CarOperation<&Car::closeWindow>;
int main()
{
Car c;
OpenDoor d;
(c.*d.f)(1);
CloseWindow e;
(c.*e.f)(2);
}
The syntax is slightly unfortunate, because apparently the .*
operator doesn't do any implicit conversion of its right operand.
Of course, this is just a very roundabout and obfuscated way of simply calling the function indicated by the type.
It would be more useful with a type that can hold a predetermined subset of the functions (like, say, DoorOperation
or Opener
types).
You can probably build that using clever template programming, but I'm not a clever template programmer.