Open ghost opened 8 years ago
Une autre par Gof< :
#include <iostream>
template<typename F>
auto operator *(int N, F fun) -> decltype((void)fun()) {
for (int i = 0; i < N; ++i)
fun();
}
int main() {
100 * []{ std::cout << "Je ne dois pas jeter d'avion en papier en classe !" << std::endl; };
}
Le decltype((void)fun())
est utile pour limiter l'instanciation de operator *
uniquement aux typename F
qui permettent de déduire le type de (void)fun()
. Donc uniquement pour les types appelables (fonctions, lambdas, functors...) et sans paramètre. C'est le principe du SFINAE. Voir aussi le std::is_callable
.
#include <iostream>
template<int N>
void loop() {
std::cout << "Je ne dois pas jeter d'avion en papier en classe !" << std::endl;
loop<N-1>();
}
template<>
void loop<0>() {
}
int main(int argc, char** argv) {
loop<100>();
return 0;
}
#include <iostream>
#include <future>
int n=100;
int main() {
if(n--) {
std::cout << "Je ne dois pas jeter d'avion en papier en classe !" << std::endl;
std::async(main).wait();
}
return 0;
}
#include <iostream>
template<int N>
void loop() {
std::cout << "Je ne dois pas jeter "
"d'avion en papier en classe" << std::endl;
if constexpr (N)
loop<N-1>();
}
int main() {
loop<99>();
}
Le decltype((void)fun())
dans ma solution est utile car ça permet de ne pas surcharger l'operateur * pour tout les types. (Utilisant SFINAE pour que ça ne fonctionne que avec des functions)
Du coup ça ne prends pas les objets fonctions?
@devnewton Cela prend tous les objets fun
qui sont valides quand on essaye de les appeler avec fun()
donc les fonctions classiques, les lambdas, les functors, les std::function
... (j'ai mis à jour ton second commentaire). Le (void)
dans decltype((void)fun())
permet de dire au decltype
de ne prendre en compte que void
(c'est une conversion de type).