
On Mon, Feb 21, 2011 at 2:37 PM, Paul Mensonides <pmenso57@comcast.net> wrote:
On Mon, 21 Feb 2011 12:57:05 -0500, Edward Diener wrote:
On 2/21/2011 3:57 AM, Paul Mensonides wrote:
Another way to provide comfort is via education. Hardcore pp- metaprogramming knowledge is not required for this.
Providing function-like syntax for invoking a macro with a variable number of parameters, as an alternative to pp-lib data syntax, is important to end-users and library developers if just for the sake of familiarity and regularity. A programmer using a "call" syntax which may be a macro or a function is not going to stop and say: this is a function so I can call it as 'somefunction(a,b,c)', this is a macro and therefore I must call it as 'somemacro((a,b,c))'. Instead he will ask that the same syntax be applied to both. You seem to feel this is wrong and that someone invoking a macro should realize that it is a macro ( and normally does because it is capital letters ) and therefore be prepared to use a different syntax, but I think that regularity in this respect is to be valued.
Most C/C++ developers perceive macro expansion mechanics to be similar to function call mechanics. I.e. where a user "calls" a macro A, and that macro "calls" the macro B, the macro B "returns" something, which is, in turn "returned" by A. That is fundamentally *not* how macro expansion behaves. The perceived similarity, where there is none (going all the way back to way before preprocessor metaprogramming) is how developers have gotten into so much trouble on account of macros.
I take serious issue with anything that intentionally perpetuates this mentality. It is one thing if the syntax required is the same by coincidence. It's another thing altogether when something is done to intentionally make it so.
It might be useful to discuss this topic using the Boost.Local `PARAMS` macro as an example. IMO, the following syntax is better from a pp metaprogramming prospective because the arguments are a proper pp data structure (i.e., a sequence) and it is very clear from the syntax that you are invoking a macro: int BOOST_LOCAL_FUNCTION_PARAMS( (int x) (const bind this) ) { // [1] ... } BOOST_LOCAL_FUNCTION_NAME(l) l(-1); However, from the users' prospective the following syntax is preferred because it looks more like a C++ function parameter declaration so they are more familiar with it: int BOOST_LOCAL_FUNCTION_PARAMS(int x, const bind this) { // [2] ... } BOOST_LOCAL_FUNCTION_NAME(l) l(-1); Therefore, as a pp metaprogrammer I'd prefer [1] but as the Boost.Local library developer I must keep in mind my users' preference and also provide [2] when variadics are available. On Mon, Feb 21, 2011 at 2:37 PM, Paul Mensonides <pmenso57@comcast.net> wrote:
I'm not terribly opposed to just BOOST_PP_TO_TUPLE(...), etc..
#define BOOST_PP_TO_TUPLE(...) (__VA_ARGS__) #define BOOST_PP_TO_ARRAY(...) \ (BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), BOOST_PP_TO_TUPLE(__VA_ARGS__) \ /**/ // BTW, an "array" is a pointless data structure // when you have variadics, but whatever #define BOOST_PP_TO_LIST(...) \ BOOST_PP_TUPLE_TO_LIST((__VA_ARGS__)) \ /**/ #define BOOST_PP_TO_SEQ(...) \ BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__)) \ /**/
I'm a lot more opposed to going back from a proper data structure to an "argument list".
IMO, it would be nice if Boost.Preprocessor supported variadics to make metaprogramming [2] easy. However, that does not necessarily mean providing: BOOST_PP_VARIADIC_TUPLE(...) I would find having these two macros just as useful (and perhaps more correct): #define BOOST_PP_TO_TUPLE(...) (__VA_ARGS__) BOOST_PP_TUPLE((...)) Then at some point in my pp metaprogram, I will have `BOOST_PP_TUPLE(BOOST_PP_TO_TUPLE(__VA_ARGS__))` which would be as convenient for me (a pp metaprogrammer) to use as `BOOST_PP_TUPLE(__VA_ARGS__)` directly. Of course, the `BOOST_PP_TO_TUPLE(__VA_ARGS__)` invocation will be hidden inside `BOOST_LOCAL_FUNCTION_PARAMS(...)` expansion to respect my library users' request that the `PARAMS` macro invocation should look like a normal C++ function parameter declaration as much as possible. In summary, I would think that providing `BOOST_PP_TO_TUPLE(...)` and `BOOST_PP_TUPLE((...))` is a good approach. -- Lorenzo