Outils pour utilisateurs

Outils du site


lang:cpp:preprocesseur

Ceci est une ancienne révision du document !


Utiliser les std::initializer_list (crochets) avec des macros

Le préprocesseur, comme le compilateur considère la virgule comme séparateur d'argument. Mais seul le compilateur considère les crochets {} comme un groupe d'argument. Le préprocesseur va considérer une virgule à l'intérieur d'un groupe de crochets comme un changement d'argument. La solution consiste à définir explicitement le type et à entourer les crochets par des parenthèses : (std::list<int>{.., .., ..}).

cpp/preprocessor/bracket.cpp
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
 
#include <list>
 
namespace
{
void f(const std::list<int>&) {}
}  // namespace
#define F(XXXX, ...) f(XXXX)
 
int main()
{
  std::list<int> c;
  f(c);
  f(std::list<int>{1, 2, 3, 4});
  f({1, 2, 3, 4});
 
  // Failed. Macro stops at first comma.
  STR(F(std::list<int>{1, 2, 3, 4}));
 
  // OK
  STR(F((std::list<int>{1, 2, 3, 4})));
 
  // OK
  STR(F(std::list<int>({1, 2, 3, 4})));
 
  // Failed. Macro stops at first comma.
  STR(F({1, 2, 3, 4}));
 
  // Failed. With double parentheses, c++ can't auto deduce std::list<std::string>.
  STR(F(({1, 2, 3, 4})));
}

Rendu :

cpp/preprocessor/bracket.cpp.i
namespace std
{
  typedef long unsigned int size_t;
  typedef long int ptrdiff_t;
  typedef decltype(nullptr) nullptr_t;
}
namespace std
{
  inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { }
}
namespace __gnu_cxx
{

On voit bien que le préprocesseur respecte les parenthèses mais pas les crochets.

Passing an initialization list to a macro Archive du 21/05/2015 le 27/08/2019

lang/cpp/preprocesseur.1594198623.txt.gz · Dernière modification : 2020/07/08 10:57 de root