Чому функція видалення_референції не працює на функції?


38

Натрапив на щось дивне, коли днями робив якусь метапрограмування шаблонів. Це в основному зводиться до цього твердження не (як я б очікував) ухваленням.

static_assert(std::is_same_v<void(), std::remove_reference_t<void()&>>);

Спочатку я думав, що роблю синтаксичну помилку, визначаючи посилання на функцію, але це твердження проходить, показуючи, що це не так.

static_assert(std::is_same_v<void()&, void()&>);

Я також спробував реалізувати remove_referenceсебе, копіюючи джерело з cppreference, але це не спрацювало. Що тут відбувається?

Відповіді:


42

Ласкаво просимо у світ типів огидних функцій.

void() &це НЕ посилання void(). Шлях до букв , що буде void(&)()(що , якщо ви remove_reference_t, ви отримаєте назад void()- це remove_reference_t робить роботу на посилання на функцію, якщо то , що ви надаєте це насправді посилання на тип функції).

Те, що void() &насправді має на увазі, - це тип функції, що має кваліфікацію члена після відключення класу. Це є:

struct C {
    void f() &;
};

Тип &C::fє void (C::*)() &. Але всі вказівники на членів можуть бути записані як T C::*для певного типу T, і в цьому випадку тип Tбуде void() &.

Див. Також P0172 .


3
Хтось повинен створити канонічне запитання щодо мерзотних типів функцій.
Брайан

Нічого собі, C ++ ніколи не здивує мене, навіть якщо я навчився і використовував його майже 10 років.
Келвін Ху

13

Ваш тип - це не посилання на функцію, а функція з класифікатором посилання .

static_assert(std::is_same_v<void()&, void()&>);
static_assert(!std::is_same_v<void()&, void(&)()>);
static_assert(std::is_same_v<void(&)(), void(&)()>);
static_assert(std::is_same_v<void(), std::remove_reference_t<void(&)()>>);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.