Demat'iNal,
En Python, les arguments d'une fonction sont évalués de gauche à droite. Le code suivant :
def dump(i):
print(i)
def foo(x, y):
...
foo(dump(0), dump(1))
Affichera ainsi un 0 suivi d'un 1.
En C++ (comme en C), nous n'avons pas de telle garantie, si bien que l'affichage est non spécifié : cela peut aussi bien être 0 suivi de 1 que 1 suivi de 0 pour :
int dump(int i) { std::cout << i << std::endl; }
void foo(int,int) {}
foo(dump(0), dump(1))
Mais avec la petite astuce suivante on peut forcer l'ordre d’exécution, car les arguments d'une initializer_list sont ordonnés (cf. https://timsong-cpp.github.io/cppwp/n3337/dcl.init.list#4) (ici en utilisant les deduction guide).
std::apply(foo, std::tuple{0, 1});
Cependant on force alors tous les arguments de foo à être passés par valeur. On peut améliorer ce comportement pour respecter les r-value etc de la façon suivante :
template<class... Ts>
class pack_args {
std::tuple<Ts...> args;
public:
pack_args(Ts... args) : args{std::forward<Ts>(args)...} {}
std::tuple<Ts...> get() && {
return std::move(args);}
};
template<class... Ts>
pack_args(Ts&&...) -> pack_args<Ts...>;
Puis
std::apply(foo, pack_args{0, 1}.get());
Comme l'illustre ce lien godbolt : https://godbolt.org/z/dTejr9336
On a ainsi ordonné les arguments d'appel sans perdre le contrôle fin du passage d'argument que permet C++.
Et voilà, une petite sucrerie de C++, probablement rien de nouveau sous le soleil pour les experts, mais ça m'a beaucoup amusé de jouer avec ça hier soir !
Et accessoirement, ça résout un bug dans Pythran, mais ça, c'est juste pour mon plaisir personnel.
# Intéressant !
Posté par vulcainman . Évalué à 1 (+1/-0).
Après un paquet d'années à faire du C++ j'étais completement passé à côté de ça… Une idée de pourquoi cet ordonnancement des arguments n'est pas garanti (au risque de causer des bugs touchy à analyser) ?
[^] # Re: Intéressant !
Posté par entwanne (site web personnel) . Évalué à 1 (+1/-0).
Je dis ça sans certitude, mais potentiellement pour des cas d'optimisations qui deviendraient impossibles si l'ordre d'évaluation était imposé.
On pourrait peut-être imaginer (si
fpeut-être transformée en fonction inline — possible qu'une certaine syntaxe soit nécessaire pour ça, je ne sais plus bien) que l'appel àcomplex_computationsoit évité puisque son résultat serait ignoré dans tous les cas.[^] # Re: Intéressant !
Posté par Colin Pitrat (site web personnel) . Évalué à 2 (+0/-0).
Pour les performances évidemment. Si évaluer le second argument en premier permet de mieux paralléliser l'exécution (en cas de dépendance dans les données, d'utilisation de ports d'exécution limités, etc …)
La majeure partie des "undefined behavior" existent pour permettre aux compilateurs d'optimiser le code.
# Fonctions pures
Posté par David Demelier (site web personnel) . Évalué à 2 (+0/-0).
La majeure partie du temps ce problème n'en est pas un dès lors que ça ne modifie pas un objet. Je me suis fait avoir une fois dans l'utilisation d'un
va_argen C il y a une dizaine d'années (sur le binding Lua-SDL2). Au moment d'analyser un format de chaine de caractère j'avais écrit :Et effectivement, surtout dans ce cas précis c'est très embettant. Le C++ a par contre corrigé un ordre d'évaluation notamment sur des expressions qui ressemblent à
foo = ++b || ++amais honnêtement je trouve pas toujours ça élégant ou lisible.AI is a mental disorder
Envoyer un commentaire
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.