Macro stringification et concatenation

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjour,

J'ai un petit soucis avec les macros.

Pour mon projet j'ai quelque macro du style

1
2
3
#define TEST_ASSERT(p_condition) Test::Assert(p_expected, 0, __FUNCTION__, __LINE__, __FILE__)
#define TEST_ASSERT_EQUAL(p_expected, p_actual) Test::Assert(p_expected, p_actual, __FUNCTION__, __LINE__, __FILE__)
/* Test::Assert est un template que l'on peut spécialiser, et qui fait en gros if(p_exepected != p_actual) error() */

Quand l'assert catch, j'ai une trace (d'où la réimplantation, je ne crash pas l'exe).

1
[ERROR | myFunction < 23 < MyFile.hpp ] Assert fail! 

Mon soucis : j'aimerais arriver à afficher les valeurs passés en paramètres de ma macro. Avec un seul paramètre c'est très simple :

1
2
3
4
//avant
#define TEST_ASSERT(p_condition) Test::Assert(p_expected, 0, __FUNCTION__, __LINE__, __FILE__)
//après
#define TEST_ASSERT(p_condition) Test::Assert(p_expected, 0, #p_condition,__FUNCTION__, __LINE__, __FILE__)

Mais, que deviens ceci ?

1
2
3
4
//avant
#define TEST_ASSERT_EQUAL(p_expected, p_actual) Test::Assert(p_expected, p_actual, __FUNCTION__, __LINE__, __FILE__)
//après (ne fonctionne pas)
#define TEST_ASSERT_EQUAL(p_expected, p_actual) Test::Assert(p_expected, p_actual, #p_exepected ## #p_actual ,__FUNCTION__, __LINE__, __FILE__)

sous clang :

1
error: pasting formed '"foo""bar"', an invalid preprocessing token

sous gcc

1
error: pasting ""foo"" and ""bar"" does not give a valid preprocessing token

(cela ne fonctionne pas également avec autre chose qu'une chaine, comme un variable par exemple).

J'ai dû louper un truc sur les macros, les pages comme la doc gcc ne m'ont pas beaucoup aidé…

oui j'utilise des macro en c++, c'est mal toussa toussa, je suis au courant ;-)

D'avance merci.

+0 -0

Cette réponse a aidé l'auteur du sujet

Passe par une macro sur 2 étages :

1
2
3
4
5
6
7
8
#define TEST_ASSERT_EQUAL_s(tok) Test::Assert(p_expected, p_actual, #tok ,__FUNCTION__, __LINE__, __FILE__)
#define TEST_ASSERT_EQUAL(p_expected, p_actual) TEST_ASSERT_EQUAL_s(p_expected##p_actual)

int main(int argc, char *argv[])
{
    TEST_ASSERT_EQUAL(foo,bar)
    return 0;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
g++ -E d.cpp
# 1 "d.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "d.cpp"
int main(int argc, char *argv[])
{
    Test::Assert(p_expected, p_actual, "foobar" ,__FUNCTION__, 6, "d.cpp")
    return 0;
}

Sinon, pourquoi ne pas utiliser un framework de test ?

Edit : ca m'apprendra à pas suivre les liens des gens.

Édité par Davidbrcz

+1 -0
Auteur du sujet

Merci pour vos réponse. Je n'utilise pas de framework de test parce que je suis sur un embarqué. Généralement les frameworks viennent avec tout un tas de dépendances, j'ai été infiniment plus vite à développer ce truc de test simpliste qu'à essayer d'adapter un machin qui marchera une fois sur 2.

+0 -0

Hormis boost (que j'ai utilisé en embarqué, OK sur de l'arm, bien qu'ancien), les frameworks de TU usuels n'ont pas de dépendance. Du moins, c'est le cas de gtest (de google), et de divers projets pour le C++11/14 dont on a fait de la pub sur reddit et dans les numéros de l'ACCU.

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte