Почему "decltype (static_cast<t>(...))" не всегда "T"?

Для следующего кода первое утверждение проходит, но второе не выполняется

template<typename T>
constexpr void assert_static_cast_identity() {
    using T_cast = decltype(static_cast<T>(std::declval<T>()));
    static_assert(std::is_same_v<T_cast, T>);
}

int main() {
    assert_static_cast_identity<int>();
    assert_static_cast_identity<int&>();
    assert_static_cast_identity<int&&>();
    // assert_static_cast_identity<int(int)>(); // illegal cast
    assert_static_cast_identity<int (&)(int)>();
    assert_static_cast_identity<int (&&)(int)>(); // static assert fails
}

Почему последнее утверждение не выполняется, и static_cast<T> не всегда возвращает T?

Ответы

Ответ 1

Это жестко закодировано в определении static_cast:

[expr.static.cast] (emphasis mine)

1 Результатом выражения static_­cast<T>(v) является результат преобразования выражения v в тип T. Если T является lvalue ссылочный тип или rvalue ссылка на тип функции, результат lvalue; если T является rvalue ссылкой на тип объекта, результат значение x; в противном случае результат является prvalue. static_­cast оператор не должен выбрасывать постоянство.

decltype уважает категорию значений своего операнда и создает ссылку lvalue для выражений lvalue.

Причина может быть в том, что сами имена функций всегда являются lvalues, и поэтому rvalue типа функции не может появляться "в дикой природе". Таким образом, приведение к этому типу, вероятно, не имеет большого смысла.