Voilà que C++ se prend pour Haskell ! Maintenant, nous avons une belle interface monadique pour std::optional, les méthodes and_then, transform, or_else, qui permettent de chainer des appels sur un optionel. Je me suis demandé si le compilo pouvait optimiser entre les appels, et j'ai donc demandé au fidèle godbolt ce quí il en pensait. Le résultat est impressionnant. Voici deux fonctions qui font la même chose, l'une utilisant l'approche monadique (g++ 12.2, options -O3 -std=c++23):
#include <optional> int f(const std::optional<int>& opt) { return opt .transform([](auto&& val) { return val + 3;}) .transform([](auto&& val) { return val - 11;}) .value_or(7); } int g(const std::optional<int>& opt) { if (opt) { return *opt + 3 - 11; } else { return 7; } }
G++, sans broncher, nous sort, dans les deux cas, le même code optimisé aux petits oignons:
cmpb $0, 4(%rdi) movl $7, %eax je .L1 movl (%rdi), %eax subl $8, %eax .L1: ret
À noter que clang, encore mieux, nous débarasse carrément du saut conditionnel !
movl (%rdi), %ecx addl $-8, %ecx cmpb $0, 4(%rdi) movl $7, %eax cmovnel %ecx, %eax retq
Ils sont forts, ces concepteurs de compilos. La conclusion, c'est donc que oui, le compilo peut optimiser à travers les appels monadiques. Mangez-en donc !