Preprocessor: Expaning empty VA_ARGS
Hello,
I have this preprocessor macros:
-----------
#include
Florian Lindner 2016-09-08 17:35:
Hello, Hi,
I have this preprocessor macros:
-----------
#include
#include #include #include <iostream>
#define TRACE(...) \ std::cout << "foo" \ BOOST_PP_SEQ_FOR_EACH_I(LOG_ARGUMENT,, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__));
#define LOG_ARGUMENT(r, data, i, elem) \ << std::endl << " Argument " << i << ": " << BOOST_PP_STRINGIZE(elem) << " == " << elem
int main(int argc, char *argv[]) { TRACE();
return 0; }
-----------
They compile when TRACE has arguments, but not without. Problem is, that LOG_ARGUMENT is called even when no args are supplied, leading to the expansion:
std::cout << "foo" << std::endl << " Argument " << 0 << ": " << "" << " == " << ;;
elem is empty, therefore there is no expression after the last <<
expected primary-expression before »;« token
How can I deal with that?
You need to check if '__VA_ARGS__' is not empty using 'BOOST_VMD_TUPLE_SIZE()'[1] or something like this[2][3]. [1] http://www.boost.org/doc/libs/1_61_0/libs/vmd/doc/html/BOOST_VMD_TUPLE_SIZE.... [2] https://github.com/niXman/nanolog/blob/master/include/nanolog/nanolog.hpp#L9... [3] https://github.com/niXman/nanolog/blob/master/include/nanolog/nanolog.hpp#L5... -- Regards, niXman ___________________________________________________ Dual-target(32 & 64-bit) MinGW-W64 compilers for 32 and 64-bit Windows: http://sourceforge.net/projects/mingw-w64/
On 9/8/2016 10:35 AM, Florian Lindner wrote:
Hello,
I have this preprocessor macros:
-----------
#include
#include #include #include <iostream>
#define TRACE(...) \ std::cout << "foo" \ BOOST_PP_SEQ_FOR_EACH_I(LOG_ARGUMENT,, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__));
#define LOG_ARGUMENT(r, data, i, elem) \ << std::endl << " Argument " << i << ": " << BOOST_PP_STRINGIZE(elem) << " == " << elem
int main(int argc, char *argv[]) { TRACE();
return 0; }
-----------
They compile when TRACE has arguments, but not without. Problem is, that LOG_ARGUMENT is called even when no args are supplied, leading to the expansion:
std::cout << "foo" << std::endl << " Argument " << 0 << ": " << "" << " == " << ;;
elem is empty, therefore there is no expression after the last <<
expected primary-expression before »;« token
How can I deal with that?
You do have variadic data, only the single variadic data element is empty. So the idea is to check for emptiness. You can do that with my VMD library and the BOOST_VMD_IS_EMPTY macro. Your preprocessing logic path should be: 1) Retrieve the first variadic element using BOOST_PP_VARIADIC_ELEM(0,__VA_ARGS__). 2) Check for emptiness of what you retrieved using BOOST_VMD_IS_EMPTY. 3) If it is not empty proceed with what you are doing above, else output nothing. I will presume you know enough about BOOST_PP control constructs to figure out the rest. I could add a macro in VMD to check if variadic data is "empty".
Am 08.09.2016 um 18:06 schrieb Edward Diener:
On 9/8/2016 10:35 AM, Florian Lindner wrote:
Hello,
I have this preprocessor macros:
-----------
#include
#include #include #include <iostream>
#define TRACE(...) \ std::cout << "foo" \ BOOST_PP_SEQ_FOR_EACH_I(LOG_ARGUMENT,, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__));
#define LOG_ARGUMENT(r, data, i, elem) \ << std::endl << " Argument " << i << ": " << BOOST_PP_STRINGIZE(elem) << " == " << elem
int main(int argc, char *argv[]) { TRACE();
return 0; }
-----------
They compile when TRACE has arguments, but not without. Problem is, that LOG_ARGUMENT is called even when no args are supplied, leading to the expansion:
std::cout << "foo" << std::endl << " Argument " << 0 << ": " << "" << " == " << ;;
elem is empty, therefore there is no expression after the last <<
expected primary-expression before »;« token
How can I deal with that?
You do have variadic data, only the single variadic data element is empty. So the idea is to check for emptiness. You can do that with my VMD library and the BOOST_VMD_IS_EMPTY macro.
Your preprocessing logic path should be:
1) Retrieve the first variadic element using BOOST_PP_VARIADIC_ELEM(0,__VA_ARGS__).
2) Check for emptiness of what you retrieved using BOOST_VMD_IS_EMPTY.
3) If it is not empty proceed with what you are doing above, else output nothing.
I will presume you know enough about BOOST_PP control constructs to figure out the rest.
Hey,
thanks for your input, from which I deviated slightly. The code looks like that now:
#include
I could add a macro in VMD to check if variadic data is "empty".
It looks like it works just fine. Best, Florian
On 9/9/2016 4:35 AM, Florian Lindner wrote:
Am 08.09.2016 um 18:06 schrieb Edward Diener:
On 9/8/2016 10:35 AM, Florian Lindner wrote:
Hello,
I have this preprocessor macros:
-----------
#include
#include #include #include <iostream>
#define TRACE(...) \ std::cout << "foo" \ BOOST_PP_SEQ_FOR_EACH_I(LOG_ARGUMENT,, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__));
#define LOG_ARGUMENT(r, data, i, elem) \ << std::endl << " Argument " << i << ": " << BOOST_PP_STRINGIZE(elem) << " == " << elem
int main(int argc, char *argv[]) { TRACE();
return 0; }
-----------
They compile when TRACE has arguments, but not without. Problem is, that LOG_ARGUMENT is called even when no args are supplied, leading to the expansion:
std::cout << "foo" << std::endl << " Argument " << 0 << ": " << "" << " == " << ;;
elem is empty, therefore there is no expression after the last <<
expected primary-expression before »;« token
How can I deal with that?
You do have variadic data, only the single variadic data element is empty. So the idea is to check for emptiness. You can do that with my VMD library and the BOOST_VMD_IS_EMPTY macro.
Your preprocessing logic path should be:
1) Retrieve the first variadic element using BOOST_PP_VARIADIC_ELEM(0,__VA_ARGS__).
2) Check for emptiness of what you retrieved using BOOST_VMD_IS_EMPTY.
3) If it is not empty proceed with what you are doing above, else output nothing.
I will presume you know enough about BOOST_PP control constructs to figure out the rest.
Hey, thanks for your input, from which I deviated slightly. The code looks like that now:
#include
#include #include #include #include
#include <iostream>
#define TRACE(...) \ std::cout << "foo" \ BOOST_PP_IF(BOOST_VMD_IS_EMPTY(__VA_ARGS__), \ BOOST_PP_EMPTY(), \ BOOST_PP_SEQ_FOR_EACH_I(LOG_ARGUMENT,, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)));
#define LOG_ARGUMENT(r, data, i, elem) \ << std::endl << " Argument " << i << ": " << BOOST_PP_STRINGIZE(elem) << " == " << elem
int main(int argc, char *argv[]) { int i = 5; std::string s = "fünf"; TRACE(); TRACE("args1", 5, s);
return 0; }
Output is:
foofoo Argument 0: "args1" == args1 Argument 1: 5 == 5 Argument 2: s == fünf%
Missing newlines are ok, in real application the output is written on a BOOST_LOG stream which adds newlines.
Do you see any problems with that?
I could add a macro in VMD to check if variadic data is "empty".
It looks like it works just fine.
Yes it does. I forgot that you can just pass the variadic data to the BOOST_VMD_IS_EMPTY macro, even after I write that macro myself <g>.
participants (3)
-
Edward Diener
-
Florian Lindner
-
niXman