1
votes

Comment transformer les modèles Variadic en plusieurs modèles uniques? (Modèle de débogage de programmation concurrentiel C ++)

Mon modèle de débogage est:

dbg(a);
dbg(n);

Quand je tape

[a]: [{1, 2, 3, 4, 5}]
[n]: [5]

où «a» est le nom du vecteur et n est la taille du vecteur. 'a' contient les éléments suivants {1, 2, 3, 4, 5} et n = 5

il imprime

[a, n]: [{1, 2, 3, 4, 5}, 5]

mais je veux qu'il imprimer

dbg(a, n);

sans avoir à taper

#define ts to_string 
string ts(char c) { return string(1, c); }
string ts(bool b) { return b ? "true" : "false"; }
string ts(const char* s) { return (string)s; }
string ts(string s) { return s; }
template<class A> string ts(complex<A> c) { 
    stringstream ss; ss << c; return ss.str(); }
string ts(vector<bool> v) { 
    string res = "{"; for(int i = 0; i < si(v); ++i) res += char('0' + v[i]);
    res += "}"; return res; }
template<size_t SZ> string ts(bitset<SZ> b) {
    string res = ""; for(int i = 0; i < SZ; ++i) res += char('0' + b[i]);
    return res; }
template<class A, class B> string ts(pair<A,B> p);
template<class T> string ts(T v) { // containers with begin(), end()
    bool fst = 1; string res = "{";
    for(const auto& x: v) {
        if (!fst) res += ", ";
        fst = 0; res += ts(x);
    }
    res += "}"; return res;
}
template<class A, class B> string ts(pair<A,B> p) {
    return "(" + ts(p.f) + ", " + ts(p.s) + ")"; }

void DBG() { cerr << "]" << endl; }
template<class H, class... T> void DBG(H h, T... t) {
    cerr << ts(h); if (sizeof...(t)) cerr << ", ";
    DBG(t...); }
#ifdef LOCAL // compile with -DLOCAL
#define dbg(...) cerr << "[" << #__VA_ARGS__ << "]: [", DBG(__VA_ARGS__)
#else
#define dbg(...) 0
#endif

Y a-t-il un moyen de le faire?

p >


2 commentaires

Surchargez la macro sur le nombre d'arguments et appelez cette macro pour chaque argument que vous passez.


Pouvez-vous s'il vous plaît décrire? Peut-être le code pour le faire? :RÉ


3 Réponses :


0
votes
// renamed from dbg
#define dbg_in(...) cerr << "[" << #__VA_ARGS__ << "]: [", DBG(__VA_ARGS__)

// overloads
#define dbg_1(_1) \
        dbg_in(_1)
#define dbg_2(_1,_2) \
        dbg_1(_1);dbg_in(_2)
#define dbg_3(_1,_2,_3) \
        dbg_2(_1,_2);dbg_in(_3)
// etc.
#define dbg_N(_1,_2,_3,_4,_5,_6,_7,_8,_9,N,...) \
        dbg_##N
#define dbg(...) \
        dbg_N(__VA_ARGS__,9,8,7,6,5,4,3,2,1)(__VA_ARGS__)

dbg(a, b);
// expands to: dbg_in(a);dbg_in(b);

5 commentaires

Cela ne fonctionne pas, il a la même sortie que la fonction de débogage d'origine. Par exemple, lorsque j'écris une simple saisie d'un vecteur et la sortie des valeurs du vecteur et de la taille du vecteur, c'est la même chose.


Fonctionne pour moi, lien godbolt


Eh bien, vous devez remplir la partie // etc. si vous voulez plus de surcharges :) et si vous voulez plus de 10, vous devez ajouter plus de _10, _11, _12, ... et 12,11,10,9, ... aux listes d'arguments de macro.


Existe-t-il un autre moyen de faire cela que de mettre manuellement 4 éléments pour dbg, 5, 6, 7, 8, .... Y a-t-il un moyen plus simple?


Pas avec les macros. Pour les macros, vous devez générer explicitement toutes les combinaisons possibles - il s'agit généralement d'un remplacement de texte. Pourtant, vous faites cela une fois (de préférence avec un script) et vivez heureux. De nombreux projets utilisent boost.preprocessor (ou je me souviens des projets P90) ou des projets similaires qui viennent avec une version de la macro "FOREACH".



0
votes

La communauté Codeforces m'a aidé et m'a indiqué la bonne solution.

dbg(a);
dbg(n);

la macro

dbg(a, n);

ne le fait pas séparément, donc

edbg(a, n);

affichera

edbg(a, n);

Alors que

edbg

affichera

#define ts to_string
string ts(char c) { return string(1, c); }
string ts(bool b) { return b ? "true" : "false"; }
string ts(const char* s) { return (string)s; }
string ts(string s) { return s; }
template<class A> string ts(complex<A> c) { 
    stringstream ss; ss << c; return ss.str(); }
string ts(vector<bool> v) { 
    string res = "{"; for(int i = 0; i < si(v); ++i) res += char('0' + v[i]);
    res += "}"; return res; }
template<size_t SZ> string ts(bitset<SZ> b) {
    string res = ""; for(int i = 0; i < SZ; ++i) res += char('0' + b[i]);
    return res; }
template<class A, class B> string ts(pair<A,B> p);
template<class T> string ts(T v) { // containers with begin(), end()
    bool fst = 1; string res = "{";
    for (const auto& x: v) {
        if (!fst) res += ", ";
        fst = 0; res += ts(x);
    }
    res += "}"; return res;
}
template<class A, class B> string ts(pair<A,B> p) {
    return "(" + ts(p.f) + ", " + ts(p.s) + ")"; }
 
// DEBUG
void DBG(string names) { string s = names; }
template<class H, class... T> void DBG(string names, H h, T... t) {
    auto pos = names.find(',');
    auto first_name = names.substr(0, pos);
    auto rest = names.substr(pos+1);
    // Strip space at the beginning
    while(rest.front() == ' '){
        rest = rest.substr(1);
    }
    cerr << "[" << first_name << "]: [" << ts(h) << "]" << nl;
    DBG(rest, t...);
}
#ifdef LOCAL
#define dbg(...) DBG(#__VA_ARGS__, __VA_ARGS__)
#else
#define dbg(...) 0
#endif
void EDBG() { cerr << "]" << endl; }
template<class H, class... T> void EDBG(H h, T... t) {
    cerr << ts(h); if (sizeof...(t)) cerr << ", ";
    EDBG(t...); }
#ifdef LOCAL // compile with -DLOCAL
#define edbg(...) cerr << "[" << #__VA_ARGS__ << "]: [", EDBG(__VA_ARGS__)
#else
#define edbg(...) 0
#endif


0 commentaires

0
votes

Le problème est que #__VA_ARGS__ ne renvoie pas une liste de chaînes, séparées par des virgules, avec les noms des variables, mais une seule chaîne, avec le nom des variables séparé par des virgules.

p> Vous devez donc diviser la chaîne d'une certaine manière.

Si vous pouvez utiliser C ++ 17, je propose la fonction suivante qui prend une seule chaîne, avec des noms séparés par des virgules, et retourne un std :: vector avec des noms uniques

#define dbg(...) dbgh(splitWords(#__VA_ARGS__), __VA_ARGS__)

et aussi un modèle variadique dbgh () (dbg helper) fonctionne comme suit

template <typename ... Ts>
void dbgh (std::vector<std::string> v, Ts const & ... ts)
 { 
   std::size_t i{};

   ((std::cerr << '[' << v[i++] << "]: [", DBG(ts)), ...);
 }

afin que vous puissiez écrire la macro variadique dbg () comme suit

std::vector<std::string> splitWords (std::string const & s)
 {
   std::regex rgx ("\\w+");

   return { std::sregex_token_iterator{s.begin(), s.end(), rgx},
            std::sregex_token_iterator{} };
 }


0 commentaires