URL: https://linuxfr.org/users/serge_ss_paille/journaux/conversion-entre-pointeurs-de-fonctions-incompatibles Title: Conversion entre pointeurs de fonctions incompatibles Authors: serge_sans_paille Date: 2018年11月07日T10:24:05+01:00 License: CC By-SA Tags: c++ Score: 14 Posons nous dans le cas suivant (oui ça commence direct) ```c++ int strange_apply(int (*f)(int) { return reinterpret_cast<(int(*)(int, int)>(f)(1, 2); } ``` Ce code compile avec un warning depuis le dernier gcc, et c'est bien car c'est en fait un *undefined behavior* (cast entre types de fonctions incompatibles dans le cas présent). Et pourtant on voit pas mal de code comme ça, p.e. dans les sources de LLVM, sous l'hypothèse que si on utilise pas les derniers arguments, ce n'est pas grave. Je me suis amusé à créer un nouveau ``function_cast`` qui permet de juste passer les valeurs dont on a besoin pour éviter cet avertissement: ```c++ #include #include template class FunctionCast; template class FunctionCast { using From = FromReturnType (*)(FromArgumentTypes...); From from; template ReturnType apply(Args args, std::index_sequence) const { return from(std::get(args)...); } public: FunctionCast(From f) : from(f) {} ReturnType operator()(ArgumentTypes... args) const { return apply(std::make_tuple(args...), std::make_index_sequence()); } }; template FunctionCast function_cast(From f) { return {f}; } int apply(int (*f)(int)) { return reinterpret_cast(f)(1, 2); // invalid return function_cast(f)(1, 2); // valid } ``` [lien godbolt ](https://godbolt.org/z/uPgyNy) illustrant l'idée. Le concept est assez simple : on empaquète les arguments dans un tuple, puis on applique la fonction en dépaquetant uniquement une partie des arguments (au passage, on doit perdre quelques informations de type, ``std::make_tuple`` n'est pas très conservateur à ce sujet). Et voilà, un nouveau cast qui, malheureusement, ne permet pas de créer de nouveaux pointeurs de fonctions mais un foncteur...

AltStyle によって変換されたページ (->オリジナル) /