web-dev-qa-db-fra.com

Pourquoi `decltype (static_cast <T> (...))` n'est pas toujours `T`?

Pour le code suivant, toutes les assertions sauf la dernière passent:

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
}

Pourquoi cette dernière assertion échoue, et static_cast<T> ne renvoyant pas toujours un T?

24
Eric

Ceci est codé en dur dans la définition de static_cast:

[expr.static.cast] (c'est moi qui souligne)

1 Le résultat de l'expression static_­cast<T>(v) est le résultat de la conversion de l'expression v en type T. Si T est un type de référence lvalue ou une référence rvalue au type de fonction, le résultat est une lvalue ; si T est une référence rvalue au type d'objet, le résultat est une xvalue; sinon, le résultat est une valeur. L'opérateur static_­cast Ne doit pas annuler la constance.

decltype respecte la catégorie de valeur de son opérande et produit une référence lvalue pour les expressions lvalue.

Le raisonnement peut être dû au fait que les noms de fonctions eux-mêmes sont toujours des valeurs l, et donc une valeur r d'un type de fonction ne peut pas apparaître "dans la nature". En tant que tel, le casting sur ce type n'a probablement aucun sens.