преобразование ссылки в функцию - PullRequest
0 голосов
/ 24 февраля 2019

Мне интересно, почему следующий код верен:

void foo(){}
void foo2(void(*)()){};
void foo3(void(*)()&){};

int main(){
  foo; // type void(&)() lvalue
  foo2(foo); // void(&)() -> void(*)() function to pointer conversion
  foo3(foo); // ?? conversion
}

Согласно function to pointer преобразованию здесь

lvalue типа функцииT может быть преобразовано в значение типа «указатель на T».Результатом является указатель на функцию.

Преобразование выполняется из void (&) () в void (*) (), но не void (*) () &.

Почему этот фрагмент кода (особенно строка с ??) является правильным?

1 Ответ

0 голосов
/ 24 февраля 2019

Параметр foo3, который равен void(*)()&, на самом деле является указателем на функцию с квалификатором ref .Это не разрешено стандартом.

Проект стандарта C ++ 17 n4659 гласит:

[dcl.fct] / 6

Тип функции с cv-qualifier-seq или ref-qualifier (включая тип с именем typedef-name) должен отображаться только как :

(6.1) - тип функции для нестатической функции-члена,
(6.2) - тип функции, к которой относится указатель на член,
(6.3) - тип функции верхнего уровня функции typedefобъявление или псевдоним-объявление,
(6.4) - идентификатор типа в аргументе по умолчанию для параметра типа, или
(6.5) - идентификатор типа для аргумента шаблона для параметра типа.

Параметр foo3 не соответствует ни одному из указанных выше критериев.Наиболее близким к тому, что вы пытаетесь сделать, является (6.2).

Таким образом, вы можете иметь это вместо:

void foo(){}
class C {
public:
    void foo1() & {}
};
void foo2(void(*)()){};
void foo3(void(C::*)()&){};

int main(){
  (void) foo; 
  foo2(foo); 
  foo3(&C::foo1); 
}

Это компилируется как в GCC, так и в Clang. Демо здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...