Quand un lambda est-il trivial?

Quand un lambda est-il garanti pour être trivial, si jamais?

J'ai supposé que s'il ne capture que des types triviaux ou rien, ce serait trivial. Je n'ai pas de standard-ese pour sauvegarder cela cependant.

Ma motivation était de déplacer du code de Visual C++ 12 à 14 et j'ai découvert que certaines affirmations statiques avaient échoué lorsqu'il s'agissait de lambdas que je supposais triviaux.

Exemple:

#include <type_traits>
#include <iostream>
using namespace std;

int main()
{
    auto lambda = [](){};

    cout << boolalpha << is_trivially_copyable<decltype(lambda)>{} << endl;
}

Ce produit false sur vs140 mais true dans vs120 et clang. Je n'ai pas pu tester gcc en raison pour ne pas avoir gcc > = 5 autour. Je m'attends à ce que ce soit une régression dans vs140, mais je ne suis pas certain du comportement correct ici.

33
demandé sur tahsmith 2015-10-07 10:27:23

2 réponses

La norme ne spécifie pas si un type de fermeture (le type d'une expression lambda) est trivial ou non. Il laisse explicitement cela à la mise en œuvre, ce qui le rend non portable. J'ai peur que vous ne puissiez pas compter sur votre static_assert produisant quelque chose de cohérent.

Citant C++14 (N4140) 5.1.2 / 3:

... Une implémentation peut définir le type de fermeture différemment de ce qui est décrit ci dessous à condition que cela ne modifie pas l'observable le comportement du programme autrement qu'en changeant:

  • la taille et / ou l'alignement du type de fermeture,
  • si le type de fermeture peut être copié trivialement (Clause 9),
  • si le type de fermeture est une classe de norme-cadre (Clause 9), ou
  • indique si le type de fermeture est une classe POD (article 9).

...

(emphase sur le mien)

Après avoir analysé la double négation dans cette phrase, Nous pouvons voir que l'implémentation est autorisée à décidez si le type de fermeture est trivialement copiable, standard layout ou POD.

Notez que le même libellé est également présent dans C++17 (N4659), [expr.prim.lambda.fermeture] 8.1.5.1/2.

31
répondu Angew 2018-08-20 08:17:02

Selon le projet de norme N4527 5.1.2/3 les expressions Lambda [expr.prim.lambda] (c'est moi qui souligne):

Le type de l'expression lambda (qui est aussi le type de objet de fermeture) est un type de classe non - union unique et sans nom-appelé le type de fermeture - dont les propriétés sont décrites ci-dessous. Ce type de classe n'est ni un agrégat (8.5.1), ni un type de littéral (3.9). Fermeture le type est déclaré dans la plus petite portée de bloc, portée de classe, ou portée de l'espace de noms contenant l'expression lambda correspondante. [ Remarque: cela détermine l'ensemble des espaces de noms et des classes associées avec le type de fermeture (3.4.2). Les types de paramètres d'un lambdadeclarator n'affecte pas ces espaces de noms associés et classe. - note de fin] une implémentation peut définir le type de fermeture différemment de ce qui est décrit ci dessous à condition que cela ne change pas le comportement observable du programme autre qu'en changeant:

(3.1 ) - la taille et / ou l'alignement du type de fermeture,

(3.2) - si le type de fermeture peut être copié trivialement (Clause 9),

(3.3) - si le le type de fermeture est une classe standard-layout (Clause 9), ou

(3.4) - si le type de fermeture est une classe de POD (article 9).

Une mise en œuvre doit n'ajoute pas de membres du type de référence rvalue au type de fermeture

Ainsi, cela dépend de l'implémentation.

14
répondu 101010 2016-08-25 11:21:32