
On Wed, Dec 15, 2010 at 6:58 PM, Dave Abrahams <dave@boostpro.com> wrote:
Eventually, that's where you should end up, IMO. But that shouldn't impair your progress now if you have momentum. See links in my previous reply for rationale.
I must have missed them, I'll take a look. On Wed, Dec 15, 2010 at 6:58 PM, Dave Abrahams <dave@boostpro.com> wrote:
You know, with C++0x you also have variadic macros, which could potentially clean up the syntax... or are you already using those?
They're used extensively and they do make things much simpler -- without variadic support, the use of the macros would be so loaded with extra parentheses and require so many more internal hacks that I probably wouldn't be working on this at all. As an example, all of the top-level macros are variadic and all of the arguments that appear to take Boost.Preprocessor sequences, such as "if" in the RandomAccessIterator concept definition I posted, actually take "variadic" preprocessor sequences, which are like Boost.Preprocessor sequences except that they can have elements with top-level commas or elements that are empty. In fact, the conditions in the code I posted make use of this if you look carefully -- the is_same and is_convertible conditions have top-level commas in them since the metafunctions are binary, which cannot be accomplished with traditional Boost.Preprocessor sequences. Also, anything that looks like a parameter list but with the types wrapped in parentheses also are implemented internally with variadic macros.
That's still a significant achievement. Great going!
Thanks. There are certain simplifications that can be made as some of those parentheses are there solely for consistency. For instance, something like ( template ( (class) It, (class) DiffT ) ) with Auto_Function could actually be written as ( template ( class It, class DiffT ) ), however, in some other places that there are parameter-list-like macro parameters I need to have the user put those extra parentheses -- the parentheses are what allow me to separate and examine each parameter when necessary. As an example, imagine: ( function_name, (int a, array< int, 5 > b) ) The problem is, in a "switch" auto function that is used for concept-based overloads, I need to forward "a" and "b", but when the parameter list is written as seen above, I have no way of actually pulling out those parameter names. Even without that comma in the "array" template argument list, it would be impossible, though commas such as that cause problems in other places that I use parameters. In the end, rather than requiring users of the macros to remember when those extra parentheses are required and when they aren't I opted to just always require them. Unfortunately that makes things look somewhat hairier. This actually isn't how I initially had the macro implemented. It used to be that some places you had to use those extra parentheses and other places you didn't. This minimized the amount of parentheses you had to use but it was hard to remember when the parentheses were required and when they weren't. With effort, I could static_assert if they were required but the user didn't provide them, but that still doesn't make the rules for when they are required any more obvious. Even with that approach, always parenthesizing also worked since I could detect if parentheses were there or not and branch out accordingly. That code is still sitting around, but I decided to stop using it since it made the implementation complicated, not to mention that the rules for when and when not to use these seemingly superfluous parentheses was complicated as well. If it turns out that the parentheses really are making things much too hairy, I could go back to making them only required in particular situations, but for the time being it's easier for me to leave them as they are, I'm sure this is much more information about the implementation than you cared to know, but I'm really trying my hardest to make this actually usable. There are unfortunately some hard limits to what is possible with the C++ preprocessor, so the end result will likely not be much simpler than what you see now. If it turns out to not be worth it, then at the very least we've learned how not to emulate concept-based overloads in C++ :p It's not a huge loss since the concepts and concept maps should still be more than usable on their own. The asserts alone, IMO, have been worth all of the effort so far. -- -Matt Calabrese