Подтвердить что ты не робот

Почему "X x; Икс();' разрешено, когда" X" определяет преобразование в указатель на функцию, но не, когда оно определяет преобразование в функтор?

void f(int){}
typedef void (*f_ptr)(int);

struct Functor{
  void operator()(int){}
};

struct X{
  operator f_ptr(){ return f; }
};

struct Y{
  operator Functor(){ return Functor(); }
};

int main(){
  X x; Y y;
  x(5); // works ?!
  y(5); // doesn't ?!
}

Пример Live на Ideone. Выход:

error: нет совпадений для вызова "(Y) (int)"

Q1: почему разрешен вызов x(5), хотя X определяет преобразование в указатель на функцию, а не operator()?

Q2: И наоборот, почему одно и то же не допускается, если мы определяем преобразование в другой функтор?

4b9b3361

Ответ 1

x(5); // works ?!

Это неявно передает x в f_ptr и вызывает это. Стандарт С++ 11:

§ 13.3.1.1.2 Вызов объекту типа класса [over.call.object]

2) Кроме того, для каждой неявной функции преобразования, объявленной в T формы

operator conversion-type-id ( ) attribute-specifier-seqopt cv-qualifier ;

[... где conversion-type-id обозначает тип "указатель на функцию (P1,...,Pn), возвращающий R"...]


y(5); // doesn't ?!

В стандарте ничего не говорится о неявном преобразовании в типы классов, которые перегружают operator() (aka functors), что подразумевает, что компилятор этого не допускает.

Вы должны явно указать его:

static_cast<Functor>(y)(5);