David Abrahams wrote:
Scott, I hate to say this, but I really think your first problem demonstrated that mpl::set is too broken to use.
Okay, I was pretty much coming to that conclusion myself. For the time being, I'll use vector and be careful about avoiding duplicate entries (practical in my case, because all I'm trying to do is develop a proof of concept). I really wish I could use what used to be referred to as typedef templates (and which now has a more general name and utility in C++0x, as I recall), but I'll swallow my desire for abstraction. I'll just hardwire vector and move on.
Well, excuse me if the following is obvious to you, but ::type is to a metafunction what actual invocation is to a run-time function. So, mpl::end<Constraints> refers to the name of the entity, but does not actually compute its "return value" unless you add the ::type suffix. I don't think this always holds.
Yeah, it always holds.
Thanks for the detailed elaboration, which I'll study when I have a bit more time. You understand this stuff better than I ever will, but I have to say that as a naive new user, BOOST_MPL_ASSERT(( mpl::equal<mpl::set<A,B>, mpl::set<A,B> > )); sure looks like I'm invoking mpl::equal and asserting that the result is true. I will remark that after reading your book and spending probably between 1 and 2 dozen hours trying to write a simple MPL-based program, the rules for when to use the ::type suffix are a complete mystery to me. Originally I just omitted it unless my code didn't compile (assuming, of course, I wanted it to compile -- sometimes the goal of TMP is to prevent something from compiling), but now I've advanced to throwing it in if my MPL program doesn't behave the way I want it to. It's still a black box to me, so if I'm mystified (not uncommon), I try my code both with and without the black box. The result is awful, I'm sure, but speaking only for myself, I think this is a necessary stage in my scramble up the learning cliff. Scott