Почему «Х х;Икс();'разрешено, когда X определяет преобразование в указатель на функцию, но нет, когда оно определяет преобразование в функтор? - PullRequest
29 голосов
/ 16 января 2012
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 ?!
}

Живой пример на Ideone . Выход:

ошибка: нет совпадения для вызова '(Y) (int)'

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

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

1 Ответ

26 голосов
/ 16 января 2012
x(5); // works ?!

Это неявно приводит x к f_ptr и вызывает это.Стандарт C ++ 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() (он же функторы), что подразумевает, что компилятор этого не допускает.

Вы должны привести егоявно:

static_cast<Functor>(y)(5);
...