
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Alexander Nasonov
Doing so just propagates a bad design (which is what it appears to be). What exactly are you doing that requires this behavior, because I guarantee there is a better, more structured, way to do it that doesn't involve ill-formed constructs or invalid sequences.
Paul, I understand your worry and I'm not going to use pp seq interface to extract arguments tuple, I'm just trying to understand whether it's possible to:
1. extract x from (x)(a,b,c) 2. remove (x) from (x)(a,b,c)
Yes, it is certainly possible. The simplest way, minus workarounds, is: #define CAT(a, b) PRIMITIVE_CAT(a, b) #define PRIMITIVE_CAT(a, b) a ## b #define SPLIT(i, im) PRIMITIVE_CAT(SPLIT_, i)(im) #define SPLIT_0(a, b) a #define SPLIT_1(a, b) b #define EXTRACT(data) SPLIT(0, EXTRACT_I data) #define EXTRACT_I(x) x, #define REMOVE(data) SPLIT(1, EXTRACT_I data)
I don't think my design is really bad, if, after all, it can be expressed in valid C++. Compare:
My only concern is that you are currently using sequence primitives on data structures that aren't sequences. They happen to work in this case. It is roughly equivalent to calling an STL algorithm with an iterator range where the end iterator cannot be reached from the begin iterator. In some cases it may well work, but there are no guarantees. With the preprocessor specifically, it is an undetectable failure to achieve a precondition. Reliance on undocumented and unguaranteed behavior *is* bad design.
BOOST_TRACE_MEM_FUN( (foo)((buf)(len)) ); BOOST_TRACE_MEM_FUN( (foo)(2, (buf,len)) ); // These two are only for pp funs ;-)
BOOST_TRACE_MEM_FUN( foo, (buf, len) ); // Comma is unnatural and looks like a typo
BOOST_TRACE_MEM_FUN( (foo)(buf, len) ); // Valid C++ call syntax. Brackets around foo can be explained in // docs.
Personally, I think that TRACE_MEM_FUN(foo, (buf, len)) is the most natural as well as the easiest to port, unless you need (at some point) access to the elements inside (buf, len), in which case I'd prefer TRACE_MEM_FUN(foo, (buf)(len)). You have two separate pieces of data, which can be supplied in multiple ways--as two distinct parameters or as a data structure. If it is passed as a data structure, it is arguably better not to use a "custom" data structure format just for slightly prettier syntax (IYO). If you use two separate parameters, it avoids the need to extract or remove anything. If you are going to use a data structure, I'd go with (foo)((buf)(len)) or (foo)((buf, len)). I'd choose the first if you ever are going to need to do anything with the two (or more) elements. Later, when variadics are generally available in C++, you can make this interface significantly better. Until then, however, nothing is going to be syntactically "perfect". Regards, Paul Mensonides