Я смотрел на эмулируемая версия nullptr и увидел этот оператор преобразования (член nullptr_t):
template<class C, class T> // or any type of null
operator T C::*() const // member pointer...
{ return 0; }
Этот синтаксис для указателя на функцию-член меня смущает. Я обычно ожидаю увидеть такой тип как что-то вроде
R (C::*)(I1, I2, ...)
С шаблоном выше нет входных аргументов. Я не могу понять, как вывод типа работает в этом случае. У меня проблемы с формированием конкретного вопроса, кроме как, как это работает? Если у меня есть такой код:
typedef int (MyClass::*MyTypedef)(float);
MyTypedef m = nullptr;
Я предполагаю, что T выводит int, а C выводит MyClass. Что «случается», чтобы плавать?
Это указатель на член, не обязательно указатель на член функция. Разница в том, что он может генерировать указатель на функцию-член или указатель на не-функцию члена.
Теперь в конкретном случае использования адресат является указателем на член, компилятор видит выражение, в котором ему нужно int (MyClass::*)(float)
и, с другой стороны, имеет nullptr
, Он пытается найти преобразование и находит operator T C::*()
, который является действительным преобразованием, если C
выводится MyClass
а также T
выводится int (float)
[Функция взятия float
и возвращая int
].
Я также нахожу этот конкретный угол языка немного запутанным (имея typedefs или выведенные типы для функций), например, это допустимо, если странный:
typedef void int_f(int);
struct X {
int_f m;
};
void X::m(int x) { std::cout << x << '\n'; }
То же самое происходит в операторе преобразования, который вас интересует.
Других решений пока нет …