On 8/14/2015 6:05 AM, Bruno Dutra wrote:
After maturing my understanding of metaprogramming a little further, I come to the conclusion eager metafunction evaluation using template aliases and lazy metafunction evaluation through explicit access of a nested ::type are two sides of the same coin and choosing one over the other is mostly just a matter of taste.
That said, I'd like to share two reasons why I prefer the lazy version:
1. Most tools for metaprogramming in the standard library are lazy, so following the principle of least surprise, lazy it shall remain
I think that's primarily, or at least in part, because alias templates didn't exist before C++11. Just because we did things that way in the past doesn't necessarily mean it's the best way now.
2. Lazy evaluation of metafunctions allow for expressive construction of "lambda expressions" as formalized by MPL
True, but in my experience, lambdas are not often needed.
I concur with Eric that functional composition is a killer feature and I strongly believe it should constitute the very core of any metaprogramming library. I just go a step further and greatly simplify things by getting rid of "metafunction classes" altogether. I've managed to transfer the entire burden of abstraction to an analogous of MPL's apply, which expects a "lambda expression" and a set of arguments and, through a handful of partial specializations, directly evaluates it. Atop apply<>, bind<> becomes a one-liner, as do everything else just as gracefully. Oh and this way one also avoids dealing with core issue #1430, since MPL's quote<> is no more.
Although interesting from a design perspective, I suspect that if you benchmark you'll find this approach is too heavy. Compile-time lambdas are expensive. Turning *every* metafunction evaluation into a lambda evaluation is going to kill compile-times. Apologies if I've misunderstood.
If one looks closer, by doing the actual recursive metafunction evaluation in a SFINAE context behind the scenes, apply<> becomes a monadic bind of metafunctions, which, from this perspective, are themselves nothing more than optionals. Such concepts bring great expressiveness to a functional world.
You refer to your eval template that returns just<Ret> or nothing? It's interesting, but essentially the same as turning evaluation failures into a SFINAE-able condition. It has the same pros and cons, too. If you get back a "nothing" from a complicated computation, you're left wondering why. I don't have a good solution to that yet.
I've been exploring this idea with my library Metal [1] (yes the name kindda sucks, I know, but it is what it is) which is an evolution of my earlier attempt of reimplementing MPL. Not that gave up on the earlier idea, it just has grown far beyond that.
Thanks, -- Eric Niebler Boost.org http://www.boost.org