Почему '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 ?!
}

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

ошибка: не соответствует вызову '(Y) (int)'

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

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


person Xeo    schedule 15.01.2012    source источник
comment
Что-то связанное со сложными правилами преобразования C++   -  person Seth Carnegie    schedule 16.01.2012
comment
@Сет: Кто бы мог подумать. :П   -  person Xeo    schedule 16.01.2012
comment
Я просто подумал, что дам вам знать, ребята :)   -  person Seth Carnegie    schedule 16.01.2012
comment
A: Должно быть, какой-то сумасшедший угловой случай. В любом случае, лучше вообще избегать операторов преобразования.   -  person BЈовић    schedule 16.01.2012


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

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

static_cast<Functor>(y)(5);
person Community    schedule 15.01.2012
comment
Вы нашли язык в спецификации C++ ISO, который специально разрешает приведение к указателю на функцию, но не к функтору. Это очень полезно! - person templatetypedef; 16.01.2012
comment
Это... не так загадочно, как я думал. :) Хотя, интересно, можно ли это считать дефектом языка... - person Xeo; 17.01.2012