sirve - programas en c++ ejemplos basicos
¿Es posible detectar el soporte de__VA_OPT__? (3)
Algo como lo siguiente debería funcionar, aunque podría mejorarlo:
#include <boost/preprocessor.hpp>
#define VA_OPT_SUPPORTED_II_1(_) 0
#define VA_OPT_SUPPORTED_II_2(_1, _2) 1
#define VA_OPT_SUPPORTED_I(...) BOOST_PP_OVERLOAD(VA_OPT_SUPPORTED_II_, __VA_OPT__(,))(__VA_OPT__(,))
#define VA_OPT_SUPPORTED VA_OPT_SUPPORTED_I(?)
En el tronco de Clang, esto se evalúa como 1 en modo C ++ 2a y 0 en modo C ++ 17. El troncal GCC en realidad lo evalúa a 1 en C ++ 17, pero también maneja __VA_OPT__
en ese modo.
Lo que esto hace es usar BOOST_PP_OVERLOAD
para llamar a la versión _1
o _2
de _II
función del número de argumentos. Si __VA_OPT__(,)
expande a ,
habrá 2 argumentos vacíos. Si no, habrá 1 argumento vacío. Siempre llamamos a esta macro con una lista de argumentos, por lo que cualquier compilador que __VA_OPT__
siempre debe expandirla a __VA_OPT__
Naturalmente, la dependencia de Boost.PP no es obligatoria. Una simple macro OVERLOAD
1-o-2-arg debería ser lo suficientemente fácil de reemplazar. Perdiendo un poco de generalidad para hacerlo más sencillo:
#define OVERLOAD2_I(_1, _2, NAME, ...) NAME
#define OVERLOAD2(NAME1, NAME2, ...) OVERLOAD2_I(__VA_ARGS__, NAME2, NAME1)
#define VA_OPT_SUPPORTED_I(...) OVERLOAD2(VA_OPT_SUPPORTED_II_1, VA_OPT_SUPPORTED_II_2, __VA_OPT__(,))(__VA_OPT__(,))
Hay una advertencia de portabilidad de Clang:
advertencia: las macros variadic son incompatibles con C ++ 98 [-Wc ++ 98-compat-pedantic]
No sé si esta detección es posible incluso sin el soporte de macro variadic C ++ 11. Podría considerar asumir que no hay soporte para los valores de __cplusplus
más bajos que C ++ 11, pero Clang todavía da la advertencia incluso cuando está envuelto en dicha comprobación.
En C ++ 20, el preprocesador admite __VA_OPT__
como una forma de expandir opcionalmente los tokens en una macro variadic si el número de argumentos es mayor que cero. (Esto evita la necesidad de la extensión ##__VA_ARGS__
GCC, que es un hack no portátil y feo).
Clang SVN ha implementado esta función, pero no han agregado una macro de prueba de características para ella. ¿Puede un pirata informático inteligente preprocesador descubrir una manera de detectar la presencia o ausencia de soporte __VA_OPT__
sin causar un error __VA_OPT__
o una advertencia de portabilidad?
Como se mencionó en la otra respuesta, puede escribir su propia macro OVERLOAD
. BOOST_PP_OVERLOAD
consta de dos partes, BOOST_PP_CAT
y BOOST_PP_VARIADIC_SIZE
. Sin embargo, a diferencia de Boost, solo te importan 2 argumentos. Asi que:
#define OVERLOAD(prefix, ...) CAT(prefix, VARIADIC(__VA_ARGS__))
CAT
se verá como
#define CAT(a, b) KITTY((a, b))
#define KITTY(par) MEOW ## par
#define MEOW(a, b) a ## b
Y VARIADIC
:
#define VARIADIC(...) _VARIADIC_(__VA_ARGS__, 2, 1,)
#define _VARIADIC_(e0, e1, size, ...) size
Inspirado por la respuesta de chris .
#define PP_THIRD_ARG(a,b,c,...) c
#define VA_OPT_SUPPORTED_I(...) PP_THIRD_ARG(__VA_OPT__(,),true,false,)
#define VA_OPT_SUPPORTED VA_OPT_SUPPORTED_I(?)
Si se admite VA_OPT_SUPPORTED_I(?)
, VA_OPT_SUPPORTED_I(?)
expande a PP_THIRD_ARG(,,true,false,)
, por lo que el tercer argumento es true
; de lo contrario, VA_OPT_SUPPORTED_I(?)
expande a PP_THIRD_ARG(__VA_OPT__(,),true,false,)
, el tercer argumento es false
.