tipos sirve que programas programa para lenguaje historia funciones features ejemplos definicion datos codigos caracteristicas basicos c++ c-preprocessor c++20

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 .