Eric Niebler
[...]
The identity function hack is a little unfortunate, but I understand the need for it.
It is, but at the same time, when you start mastering it, it becomes a powerful way of controlling exactly what should be deferred and what shouldn't. I agree that for 80% of the use cases, it would be better if the compiler could just "figure it out" himself.
What if the two branches return different types? It seems like it /should/ work when passed a runtime int like 11, as well as when passed a compile-time integral constant wrapper like std::integral_constant
. Is that how it works? That would be nifty.
Having both branches return objects of different types is definitely possible. Actually, the whole thing was designed to make this possible. However, in order for the branches to be able to return unrelated objects, i.e. ones without a common_type, the condition has to be known at compile-time (e.g. an IntegralConstant). If the eval_if is passed a runtime Logical (say a bool or an int), then both branches must return objects with a common_type. For example: Works: std::string s = eval_if(true_, // IntegralConstant condition [](auto _) { return std::string{"abcd"}; }, [](auto _) { return 1; } ); double d = eval_if(true, // bool condition [](auto _) { return 3.4; }, [](auto _) { return 1; } ); Fails (std::string and int don't share a common type): eval_if(true, [](auto _) { return std::string{"abcd"}; }, [](auto _) { return 1; } );
[...]
Using lambdas for lazy conditionals brings limitations and pitfalls. Would you consider adding a pure type-level alternative for people doing straight metaprogramming?
I think that might be a good idea. More generally, It might be possible to provide a mini EDSL for lambda expressions that could look like Proto's transforms? I'm really just thinking out loud, but what do you think? For simple laziness, Hana also has a tool called `lazy`, which allows creating function calls that can be evaluated later. For example: // nothing is evaluated nor instantiated at this point auto lazy_result = lazy(f)(x1, x2, x3); // everything happens now auto result = eval(lazy_result); Lazy is a Monad, which allows chaining lazy computations as shown in [1]. However, Lazy is not integrated with eval_if right now, which makes it pretty much useless. The reason why it is not integrated is because I think it can also be made a Comonad, and I wanted to see how lazy branching might be generalizable to arbitrary Comonads. I haven't had the time to explore this further for now though. Regards, Louis [1]: http://ldionne.github.io/hana/structboost_1_1hana_1_1_lazy.html