Dlaczego `decltype (static_cast <T> (…))` nie zawsze `T`?

24

W przypadku następującego kodu wszystkie twierdzenia oprócz ostatniego są przekazywane:

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
}

Dlaczego to ostatnie stwierdzenie zawodzi i static_cast<T>nie zawsze zwraca a T?

Eric
źródło
Daję T_cast i{1};, rozumiem invalid initialization of non-const reference of type 'T_cast' {aka 'int (&)(int)'} from an rvalue of type '<brace-enclosed initializer list>', więc z jakiegokolwiek powodu T_castjest int (&)(int)raczej niż int (&&)(int).
Kevin

Odpowiedzi:

21

Jest to zapisane w definicji static_cast:

[expr.static.cast] (moje wyróżnienie )

1 Wynik wyrażenia static_­cast<T>(v)jest wynikiem konwersji wyrażenia vna typ T. Jeśli Tjest to typ odwołania do wartości lub odwołanie do typu funkcji, wynikiem jest wartość ; jeśli Tjest odwołaniem do wartości typu obiektu, wynikiem jest wartość x; w przeciwnym razie wynik jest wartością. static_­cast Operator nie odrzucił constness.

decltype szanuje kategorię wartości swojego argumentu i tworzy odwołanie do wartości dla wyrażeń wartości.

Rozumowanie może wynikać z tego, że same nazwy funkcji zawsze są wartościami, dlatego wartość typu funkcji nie może pojawić się „na wolności”. Jako takie, rzutowanie na ten typ prawdopodobnie nie ma sensu.

StoryTeller - Unslander Monica
źródło
to pytanie dotyczy bardziej szczegółowo „wartości [s] typu funkcji [nie] pojawiają się [ing]„ na wolności ””
Eric,