auto max_impl(First first, Rest... rest) { return max_impl( // appel au cas terminal avec 2 arguments first, // appel "récursif" au template (avec un paramètre/argument de moins), // ou au cas terminal si 'rest' est de longueur 2 max_impl(rest...) ); };
void main() { #if 0 // Utilisation incorrecte avec zéro argument std::cout << max() << std::endl; // => Ne compile pas : error: static_assert failed "max needs at least 1 argument" #endif #if 0 // Utilisation incorrecte avec zéro argument (bypasse le point d'entrée et appel direct de l'implantation max_impl) std::cout << max_impl() << std::endl; // => Ne compile pas : error: no matching function for call to 'max_impl' #endif std::cout << max(2) << std::endl; // => Affiche "2" std::cout << max(2, 1) << std::endl; // => Affiche "2" std::cout << max(2, 1, 6) << std::endl; // => Affiche "6" // Fonctionne avec tout type qui implante l'opérateur > std::string s1{"def"}, s2{"abc"}; std::cout << max(s1, s2) << std::endl; // => Affiche "def" // Attention tout de même! l'opérateur > ici compare les adresses std::cout << max(s1.c_str(), s2.c_str()) << std::endl; // => Affiche "abc" sur ma machine // Attention tout de même! l'opérateur > ici compare les adresses char a1[]{"abc"}, a2[]{"def"}, a3[]{"abc"}; std::cout << max(a1, a2) << std::endl; // => Affiche "abc" sur ma machine std::cout << max(a2, a3) << std::endl; // => Affiche "def" sur ma machine // Fonctionne très bien avec des types hétérogènes std::cout << max(2, 1.0, 6.0f, 4ull) << std::endl; // => Affiche "6" // Voyons quel est le type du résultat ... auto result = max(2, 1.0, 6.0f, 4ull); std::cout << demangle(typeid(result).name()) << std::endl; // => Affiche "double" #if 0 // Vérification statique (à la compilation) que les types sont compatibles std::cout << max(s1, 123) << std::endl; // => Ne compile pas : error: invalid operands to binary expression ('std::basic_string<char>' and 'int') #endif }
auto max(T... args) { static_assert(sizeof...(args) > 0, "max needs at least 1 argument"); return max_impl(args...); };
constexpr int max() { return max_impl(Ts...); }
constexpr int max_impl(int r, int i, int ints...) { return i > r ? max_impl(i, ints) : max_impl(r, ints); }