37 votes

La relation entre auto et decltype

Est

 auto x = initializer;
 

équivalent à

 decltype(initializer) x = initializer;
 

ou

 decltype((initializer)) x = initializer;
 

ou non?

40voto

Nawaz Points 148870

decltype estime également que l'expression est rvalue ou lvalue .

Wikipédia dit,

Le type indiqué par decltype peut être différent du type de déduire de l'auto.

#include <vector>
int main()
{
    const std::vector<int> v(1);
    auto a = v[0];        // a has type int
    decltype(v[0]) b = 1; // b has type const int&, the return type of
                        // std::vector<int>::operator[](size_type) const
    auto c = 0;           // c has type int
    auto d = c;           // d has type int
    decltype(c) e;        // e has type int, the type of the entity named by c
    decltype((c)) f = c;  // f has type int&, because (c) is an lvalue
    decltype(0) g;        // g has type int, because 0 is an rvalue
}

C'est à peu près explique la différence importante. Avis decltype(c) et decltype((c)) ne sont pas les mêmes!

Et parfois, auto et decltype travaille ensemble dans un esprit de coopération, comme dans l'exemple suivant (tiré de wiki, et un peu modifié):

int& foo(int& i);
float foo(float& f);

template <class T>
auto f(T& t) −> decltype(foo(t)) 
{
  return foo(t);
}

Wikipedia plus explique la sémantique de l' decltype comme suit:

De même pour l'opérateur sizeof, l'opérande de decltype est non évaluée. De manière informelle, le type retourné par decltype(e) est déduite comme suit:

  • Si l'expression e fait référence à une variable locale ou de l'espace de la portée, à un membre statique variable ou un paramètre de fonction, alors le résultat est que la variable ou d'un paramètre de type déclaré de
  • Si e est un appel de fonction ou un opérateur surchargé invocation, decltype(e) désigne la déclaration de type de retour de cette fonction
  • Sinon, si e est une lvalue, decltype(e) est en T&, où T est le type de e; si e est une rvalue, le résultat est T

Ces sémantiques ont été conçus pour répondre aux besoins de la bibliothèque générique des écrivains, alors que dans le même temps, d'être intuitif pour les programmeurs débutants, parce que le type de retour de decltype correspond toujours au type de l'objet ou de la fonction exactement comme il l'a déclaré dans le code source. Plus formellement, la Règle 1 s'applique sans parenthèse id-expressions et membre de la classe des expressions dont l'accès. Pour les appels de fonction, le déduit type est le type de retour de la statique fonction choisie, tel que déterminé par les règles pour la résolution de surcharge. Exemple:

const int&& foo();
int i;
struct A { double x; };
const A* a = new A();
decltype(foo()) x1; // type is const int&&
decltype(i) x2; // type is int
decltype(a->x) x3; // type is double
decltype((a->x)) x4; // type is const double&

La raison de la différence entre ces deux invocations de decltype est que la mise entre parenthèses de l'expression (a->x) est ni un id d'expression, ni membre de l'accès à l'expression, et, par conséquent, ne désigne pas un objet nommé.Parce que l'expression est une lvalue, ses déduit de type "référence pour le type de l'expression", ou const double&.

10voto

Alexandre C. Points 31758

Cela ne fonctionnera pas (et c'est moche):

 decltype([]() { foo(); }) f = []() { foo(); };
 

tandis que

 auto f = []() { foo(); };
 

volonté.

8voto

Luc Danton Points 21421

Il dépend. auto et decltype servent à des fins différentes, donc ils n'ont pas de carte un-à-un.

Les règles d' auto sont les plus faciles à expliquer, car ils sont les mêmes que pour le paramètre de modèle de déduction. Je ne vais pas développer ici, mais notez que l' auto& et auto&& sont également quelques utilisations possibles!

decltype a cependant plusieurs cas, dont certains que vous avez illustré ci-dessus (l'information et de citations tirées de n3290, 7.1.6.2 Simple spécificateurs de type [dcl.type.simple]) que j'ai séparé en deux catégories:

  • lors de l'utilisation de ce que la Norme appelle "une sans parenthèse id-expression ou un sans parenthèse membre de la classe d'accès"
  • le reste!

Officieusement, je dirais que c' decltype peut opérer sur les deux noms (pour le premier cas) ou des expressions. (Officiellement, et selon la grammaire decltype fonctionne sur des expressions, pensez donc à le premier cas comme un raffinement et le deuxième cas, comme un fourre-tout.)

Lors de l'utilisation d'un nom avec decltype, vous obtenez l' a déclaré le type de l'entité. Ainsi, par exemple, decltype(an_object.a_member) est le type de membre tel qu'il apparaît dans la définition de la classe. D'autre part, si nous utilisons decltype( (an_object.a_member) ) nous nous trouvons dans le fourre-tout cas et nous sommes en inspectant le type de l'expression , telle qu'elle apparaît dans le code.

En conséquence, la façon de couvrir tous les cas de vos questions:

int initializer;
auto x = initializer; // type int
// equivalent since initializer was declared as int
decltype(initializer) y = initializer;


enum E { initializer };
auto x = initializer; // type E
// equivalent because the expression is a prvalue of type E
decltype( (initializer) ) y = initializer;


struct {
    int const& ializer;
} init { 0 };
auto x = init.ializer; // type int
// not equivalent because declared type is int const&
// decltype(init.ializer) y = init.ializer;
// not equivalent because the expression is an lvalue of type int const&
// decltype( (init.ializer) ) y = init.ializer;

1voto

iammilind Points 29275
  1. Si initializer est un tableau, alors decltype(x) ou decltype((x)) ne fonctionnent pas simplement dessus. Cependant, auto seront déduits d'un pointeur.
  2. Si initializer est une fonction, alors l'application de decltype(fp) sera déduite du type de fonction, auto sera déduite de son type de retour.

Donc, en général, auto ne peut pas être considéré comme un remplacement de la version decltype() vous avez demandée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X