Boost logo

Boost :

Subject: Re: [boost] Boost Hana comments
From: Jeremy Maitin-Shepard (jeremy_at_[hidden])
Date: 2014-08-19 20:36:05

Louis Dionne <ldionne.2 <at>> writes:
> Sorry for the slow answer; I completely missed your message.

No problem.

> Jeremy Maitin-Shepard <jeremy <at>> writes:
> > Integral data type:
> > -------------------
> >
> > It would be better not to duplicate std::integral_constant. However, I
> > recognize that the overloaded operators are useful and you wouldn't be
> > able
> > to do this with std::integral_constant (well, I suppose you still could,
> > but
> > as they wouldn't be found by ADL, they wouldn't be terribly useful). This
> > rationale (assuming it is correct) should be documented though.
> This is part of the rationale. There's also the fact that integral_constant
> requires including <type_traits>, which is about the size of the whole
> library;
> I find this annoying. I'll document that.

I didn't think about that. It seems to me though that most headers that do
metaprogramming will also require type_traits anyway. Still, it is great to
minimize dependencies when possible.

> > Logical type class:
> > -------------------
> >
> > What is really gained by making this a type class at all?
> Yes; how would you branch at compile-time otherwise? The if_ method for e.g.
> Integrals is not equivalent to a normal C++ if-statement; it allows both
> branches to have different and incompatible types. Also, since we want to
> be able to branch on `integral`s but also on `mpl::integral_c`s, we need a
> type class.

As I see it, there are two types of Logical: compile-time and run-time.
Both cases have to be handled separately, and there needs to be a way to
figure out which type of logical a given argument is, but that is it. The
implementation of eval_if will be the same, modulo some change of names, for
hana integral, mpl::integral_c, and std::integral_constant.

> > It seems that and_ and or_ require that all arguments be of the same "hana
> > datatype", though actually this isn't documented anywhere and this might
> > not
> > even be the precise requirement (but obviously it needs to be documented
> > very explicitly, and this probably applies to almost every method in
> > Hana).
> >
> > Really we really should be able to mix multiple data types in a call to
> > or_
> > or and_, though. Otherwise the usability is unreasonably limited. Of
> > course there is then the question of return type. However, I would assume
> > most users would be happy getting back either a Hana Integral or a bool,
> > depending on whether it is a compile-time or runtime condition. Certainly
> > this would be better than getting back a compiler error.
> The arguments of `and_` and `or_` only need to be Logicals. I'll document
> it.
> > Another question: how does the performance of and_ and or_ compare to the
> > optimized verions you showed in your MPL11 talk?
> I haven't benchmarked that yet, but I expect it to be significantly less
> efficient. I'll have to think about a way of specifying the requirements
> of `Logical` in a way that makes optimizations possible, which is not the
> case currently.

Maybe and_ and or_ could just be optimized for hana integral_c. Since the
goal is efficiency it seems it may be hard to have it more generic.

> > Pair datatype:
> > --------------
> >
> > Why duplicate std::pair?
> For the same reason as `std::integral_constant`; operators.

Which operators? I don't see any documented. There are the first and
second methods which perhaps can be found by ADL, but that hardly seems like
a reasonable justification for making another pair type.

> > Alternatively, why duplicate list?
> >
> > Perhaps list should just define first and second as well?
> >
> > Product type class:
> > ----------------
> >
> > Why isn't a 2-element List, a 2-element std::tuple, etc. an instance?
> `hana::list`, `std::tuple` and friends can't be made an instance of the
> `Product` type class because they would not satisfy its laws.

>From my reading of the description of the Product type class laws, the
problem you are referring to is the uniqueness requirement on the function
"make": for a tuple, you could add more than two elements, with the extra
elements containing arbitrary unused values.

However, I don't see any practical reason why it is useful to have a
separate Product type from a Tuple type. Potentially, you could document
that first and second are only valid for 2-element tuples, and make them
fail for tuples with more than 2 elements. However, particularly since we
are just talking about metaprogramming, it seems letting them work for any
tuple would be better.

> > List type class:
> > ----------------
> >
> > Just as for Logical, it would be useful to be able to mix datatypes in
> > calls
> > to concat, zip, zip_with.
> I agree, but it would then be harder to implement those operations
> efficiently,
> since you would not control the representation of all the arguments. I'll
> think about a way of supporting different data types while still allowing
> optimizations.


> > The list function itself shouldn't be documented as part of the type
> > class,
> > since it isn't logically part of it.
> That's because `List` was both a data type and a type class. In my local
> version, `List` is only a type class and the data type is named `Tuple`
> instead, which makes this a non-issue.

Okay, great.

> > What about get<N>, get<N,M> accessors? I understand these can be defined
> > in
> > terms of the other methods, but clearly they are useful on their own.
> For `get<N>`, I'll provide an helper method `at_c<N>(iterable)`. I don't
> understand what you mean by `get<N, M>` though. What does `get<N, M>` do?

Perhaps get_range would be a better name. The idea would be to return a
sequence (get<N>, get<N+1>, ..., get<M-1>).

Boost list run by bdawes at, gregod at, cpdaniel at, john at