Bonjour,
Aujourd’hui je tombe sur une petite chose que je ne m’explique pas très bien…
Fichier strings.hpp
1 2 3 4 5 6 7 | template<int N> inline std::string format (const std::string& fmt) { return fmt; } template<int N=1, class A, class... L> inline std::string format (const std::string& fmt, const A& arg, L... others) { return format<N+1>( boost::replace_all_copy(fmt, '%' + to_string(N), to_string(arg)), std::forward<L>(others)...); } |
Que fait ce code ? C’est un genre de mini sprintf++. IL s’utilise comme ceci:
1 | string message = format("Bonjour, je m'appelle %1 et j'ai %2 ans", "Bob", 28); |
ET on peut passer en paramètre n’importe quoi, pourvu qu’il existe une version de std::string to_string(const T&);
. IL en existe en standard C++17 ou sinon comme pour moi avec MinGW32 (GCC 5.3) où je ne les ai pas, ça se définit facilement.
Jusque là ça fonctionne super bien.
Là où je ne comprends plus, c’est à partir d’ici. J’ai un second fichier avec ceci:
quelquechose.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include "strings.hpp" ... // Une nouvelle surcharge de la fameuse fonction to_string, dont je n'ai besoin que localement static inline string to_string (const pair<int,int>& p) { ... } ... int a=1, b=2, c=3, d=4; string message = format("%1 et %2.", make_pair(a,b), make_pair(c,d)); |
ET là, ça ne compile pas. Je me ramasse la tonne de messages d’erreur pour me dire qu’il ne peut pas instancier ma fonction template format parce qu’il ne trouve pas la fonction std::string to_string(const std::pair<int,int>&);
. IL m’énumère toutes les autres version existantes comme potentielles candidates, mais c’est comme si celle que je venais de définir localement n’existait pas, elle n’est pas listée.
Juste pour voir, j’enlève static, j’enlève inline dans la définition de ma surcharge de to_string; ça ne passe pas mieux.
Je tente aussi de définir ma surcharge avant l’include de strings.hpp. Ah ben non, ça veut pas non plus.
J’ajoute le prototype dans strings.hpp et là, bizarrement, ça marche. LE prototype est défini en inline et la fonction elle-même dans mon fichier .cpp est toujours static inline; et ça compile.
Pourquoi il a absolument besoin du prototype dans strings.hpp ? ET comment ça se fait que ça marche même avec static inline ? ET pourquoi même si je définis la fonction avant l’include, ça ne passe pas ?
Je croyais qu’il ne vérifiait l’existance de la bonne version de to_string qu’au moment de l’instantiation, donc dans mon .cpp et après que’lle ait été bien définie ?
Ca m’aurais arrangé de ne pas toucher strings.hpp vu que cette surcharge particulière n’est utilisée que dans ce seul fichier .cpp précisément. J’utilise strings.hpp dans plusieurs projets différents qui n’ont rien à voir les uns avec les autres.
Merci pour vos réponses.
EDIT: orthographe