Почему remove_reference не работает с функциями?

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(&)()>>);
0x5453
источник