44 votes

Quels sont les contextes non évaluée en C++?

Un exemple qui vient souvent à l'esprit est :

sizeof expression, où il n'est pas d'évaluer l'expression, mais détermine la taille par type statique. Par exemple :

int func();
sizeof(func());

C'est ma limite de la pensée, donc si il y a d'autres contextes non évaluée, alors quels sont-ils?

39voto

5gon12eder Points 2904

Heureusement, le standard a une liste pratique de ceux-ci (§ 5 [expr] ¶ 8):

Dans certains contextes, non évaluée opérandes apparaissent (5.2.8, 5.3.3, 5.3.7, 7.1.6.2). Non évalué opérande n'est pas évalué. Non évalué opérande est considéré comme une pleine expression.

Regardons en détail.

Je vais utiliser les déclarations suivantes dans mes exemples. Les fonctions déclarées ne sont jamais définie n'importe où, alors si un appel apparaît dans un évalués contexte, le programme est mal formé et nous allons obtenir un lien à l'erreur. En les appelant non évalué contexte est très bien, cependant.

int foo();  // never defined anywhere

struct widget
{
  virtual ~widget();
  static widget& get_instance();  // never defined anywhere
};

typeid

§ 5.2.8 [expr.typeid] ¶ 3:

Lors de l' typeid est appliquée à une expression autre qu'un glvalue d'un polymorphe type de classe, le résultat fait référence à un std::type_info objet représentant le type statique de l'expression. Lvalue-à-rvalue (4.1), tableau de pointeur (4.2), et la fonction de pointeur (4.3) les conversions ne sont pas appliquées à l'expression. Si le type de l'expression est un type de classe, la classe doit être complètement défini. L'expression est un opérande non évaluée (Alinéa 5).

Remarque l'a souligné exception pour polymorphes cours ( class avec au moins un virtual membre).

Donc, c'est bien

typeid( foo() )

et donne un std::type_info objet pour int alors que ce

typeid( widget::get_instance() )

n'est pas et ne sera probablement produire un lien erreur. Il a à évaluer l'opérande parce que le type dynamique est déterminée par la recherche de la vptr au moment de l'exécution.

<coup de gueule>je trouve ça assez déroutant que le fait de savoir si ou non le type statique de l'opérande est polymorphe de la sémantique de l'opérateur dans de telles spectaculaires, mais subtile, des moyens.</coup de gueule>

sizeof

§ 5.3.3 [expr.sizeof] ¶ 1:

L' sizeof opérateur donne le nombre d'octets dans la représentation des objets de son opérande. L'opérande est soit une expression, qui est un non évaluée opérande (Alinéa 5), ou d'une mise entre parenthèses de type id. L' sizeof exploitant ne doit pas être appliquée à une expression qui a la fonction ou de type incomplète, à un type d'énumération dont le type sous-jacent n'est pas fixe, avant de l'ensemble de ses agents recenseurs ont été déclarés, à la mise entre parenthèses du nom de ces types, ou à un glvalue qui désigne un peu de champ.

La suite

sizeof( foo() )

est parfaitement bien, et équivalente à sizeof(int).

sizeof( widget::get_instance() )

est aussi permis. Notez, cependant, que c'est équivalent à sizeof(widget) et donc sans doute pas très utile sur un polymorphe return type.

noexcept

§ 5.3.7 [expr.unaire.noexcept] ¶ 1:

L' noexcept opérateur détermine si l'évaluation de son opérande, ce qui est un non évaluée opérande (Alinéa 5), peut lever une exception (15.1).

L'expression

noexcept( foo() )

est valide et évalue false.

Voici un exemple plus réaliste exemple qui est aussi valable.

void bar() noexcept(noexcept( widget::get_instance() ));

Notez que seuls les intérieurs noexcept est l'opérateur tandis que l'extérieur est le spécificateur.

decltype

§ 7.1.6.2 [dcl.type.simple] ¶ 4.4:

L'opérande de l' decltype spécificateur est un non évaluée opérande (Alinéa 5).

La déclaration

decltype( foo() ) n = 42;

déclare une variable n de type int et l'initialise avec la valeur 42.

auto baz() -> decltype( widget::get_instance() );

déclare une fonction baz qui ne prend pas d'arguments et d' returns - widget&.

Et c'est tout ce qu'il y a (comme en C++14).

8voto

NathanOliver Points 10062

La durée standard est un non évaluée opérande et vous pouvez le trouver dans [expr]

Dans certains contextes, non évaluée opérandes apparaissent (5.2.8, 5.3.3, 5.3.7, 7.1.6.2). Non évalué opérande n'est pas évalué. Non évalué opérande est considéré comme une pleine expression. [ Note: non évalué opérande, un non-membre de classe statique peut être nommé (5.1) et de nommer des objets ou des fonctions n'est pas, par elle-même, exiger qu'une définition précise (3.2). -la note de fin ]

  • 5.2.8 couvre typeid
  • 5.3.3 couvre sizeof
  • 5.3.7 couvre noexcept
  • 7.1.6.2 couvre simple spécificateurs de type comme auto et decltype et la GOUSSE de type int, char, double etc.

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