Discussion:
[boost] [review][mp11] Formal review of Mp11
Bjorn Reese via Boost
2017-07-15 10:19:04 UTC
Permalink
The formal review of Peter Dimov's Mp11 library is scheduled for
July 15 - July 24, 2017 [1].

Mp11 is a C++11 metaprogramming library for compile-time manipulation of
data structures that contain types. It’s based on template aliases and
variadic templates and implements the approach outlined in the article
"Simple C++ metaprogramming" [2] and its sequel [3]. These articles are
useful background information for the review.

* Mp11 aims to make simple usage simple, and to support complex usage
without complicating the simple use cases.

* Mp11 works on any type-list, whether its own type-list mp_list,
or standard type-lists such as std::tuple and std::variant, or
user-defined type-lists.

* Mp11 works with any meta-function, such as C++11 or Boost
type-traits, or user-defined type-traits.

Mp11 can be found here:

* Documentation: https://rawgit.com/pdimov/mp11/master/doc/html/mp11.html

* Source code: https://github.com/pdimov/mp11/tree/master


Please answer the following questions in your review [4]:

1. Should Mp11 be accepted into Boost? Please state all conditions
for acceptance explicity.

2. What is your evaluation of the design?

3. What is your evaluation of the implementation?

4. What is your evaluation of the documentation?

5. What is your evaluation of the potential usefulness of the library?

6. Did you try to use the library? With what compiler? Did you have
any problems?

7. How much effort did you put into your evaluation? A glance? A quick
reading? In-depth study?

8. Are you knowledgeable about the problem domain?


[1] http://www.boost.org/community/review_schedule.html
[2] http://pdimov.com/cpp2/simple_cxx11_metaprogramming.html
[3] http://pdimov.com/cpp2/simple_cxx11_metaprogramming_2.html
[4] http://www.boost.org/community/reviews.html

_______________________________________________
Unsubscribe & other changes: h
Vinnie Falco via Boost
2017-07-15 12:18:22 UTC
Permalink
On Sat, Jul 15, 2017 at 3:19 AM, Bjorn Reese via Boost
<***@lists.boost.org> wrote:
> * Documentation: https://rawgit.com/pdimov/mp11/master/doc/html/mp11.html

Is there a rationale explaining how mp11 differentiates itself from
the numerous other metaprogramming libraries, some in Boost? Why does
Boost need yet another one of these things?

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Peter Dimov via Boost
2017-07-15 12:39:45 UTC
Permalink
Vinnie Falco wrote:

> > * Documentation:
> > https://rawgit.com/pdimov/mp11/master/doc/html/mp11.html
>
> Is there a rationale explaining how mp11 differentiates itself from the
> numerous other metaprogramming libraries, some in Boost? Why does Boost
> need yet another one of these things?

Mp11 differentiates itself from Boost.MPL by being based on C++11 constructs
such as template aliases and variadic templates.

Compared to Boost.Hana, Mp11 offers pure type-based metaprogramming. This
more limited scope in practice translates to more compilers supported and
faster compile times.

If we look outside Boost, compared to Metal, the main difference is that
Mp11 is generic with respect to the List and Number concepts; it works with
std::tuple, std::pair, std::variant, the lot, and it supports type traits of
the is_const variety directly.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Vinnie Falco via Boost
2017-07-15 12:36:20 UTC
Permalink
On Sat, Jul 15, 2017 at 3:19 AM, Bjorn Reese via Boost
<***@lists.boost.org> wrote:
> The formal review of Peter Dimov's Mp11 library is scheduled for
> July 15 - July 24, 2017 [1].

* The documentation states: "mp_if_c<true, T, E…> is an alias for T.
mp_if_c<false, T, E> is an alias for E. Otherwise, the result is a
substitution failure."

Should that read "mp_if_c<false, T, E...>"? If not, why? And shouldn't
the document address it?

_______________________________________________
Unsubscribe & other c
Peter Dimov via Boost
2017-07-15 12:47:57 UTC
Permalink
Vinnie Falco wrote:

> * The documentation states: "mp_if_c<true, T, E…> is an alias for T.
> mp_if_c<false, T, E> is an alias for E. Otherwise, the result is a
> substitution failure."
>
> Should that read "mp_if_c<false, T, E...>"? If not, why?

No.

The idea here is that mp_if_c can be used in two ways. One is mp_if_c<Cond,
T, E>, which gives either T or E depending on Cond. The other is
mp_if_c<Cond, T>, which is the same as std::enable_if_t<Cond, T> - gives T
when Cond, otherwise a substitution failure.

So

mp_if_c<true, T> is T
mp_if_c<true, T, E> is T
mp_if_c<false, T, E> is E

Aliases can't be specialized, so it's not possible to implement just the
above, which is why it takes a parameter pack for E... and does

mp_if_c<true, T, E...> is T
mp_if_c<false, T, E> is E

which for the three cases we're interested in gives the results we need.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org
Andrey Semashev via Boost
2017-07-15 12:57:28 UTC
Permalink
On 07/15/17 15:47, Peter Dimov via Boost wrote:
> Vinnie Falco wrote:
>
>> * The documentation states: "mp_if_c<true, T, E…> is an alias for T.
>> mp_if_c<false, T, E> is an alias for E. Otherwise, the result is a
>> substitution failure."
>>
>> Should that read "mp_if_c<false, T, E...>"? If not, why?
>
> No.
>
> The idea here is that mp_if_c can be used in two ways. One is
> mp_if_c<Cond, T, E>, which gives either T or E depending on Cond. The
> other is mp_if_c<Cond, T>, which is the same as std::enable_if_t<Cond,
> T> - gives T when Cond, otherwise a substitution failure.
>
> So
>
> mp_if_c<true, T> is T
> mp_if_c<true, T, E> is T
> mp_if_c<false, T, E> is E
>
> Aliases can't be specialized, so it's not possible to implement just the
> above, which is why it takes a parameter pack for E... and does
>
> mp_if_c<true, T, E...> is T
> mp_if_c<false, T, E> is E
>
> which for the three cases we're interested in gives the results we need.

Why not separate the two use case into two primitives? We usually want
one or the other and different tools would make sense, at least for
documenting purpose.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boo
Joshua Berne via Boost
2017-07-15 13:08:01 UTC
Permalink
I think for people who don't use packs often the fact that the E... pack
is being used essentially to make E optional is a source of confusion.

The way it's implemented, you can also pass more than one type in the else
to mp_if_c when the condition is true, but not if it's false. Maybe you
couuld separate the detail::mp_if_c_impl into 2 specializations for the
true case, one with a single else and one with no else type. Then passing
multiple else types would always fail substituation whether or not the
condition is true or false.

Then I'd change the documentation to list out those two separate true
cases and make no mention of the E..., or if you want you could say
mp_if_c<bool,T,E1,E2,Es...> will always fail substituation explicitly in
the documentation (but that again just seems like adding confusion.)

- Josh

On Sat, 15 Jul 2017, Andrey Semashev via Boost wrote:

> On 07/15/17 15:47, Peter Dimov via Boost wrote:
>> Vinnie Falco wrote:
>>
>>> * The documentation states: "mp_if_c<true, T, E…> is an alias for T.
>>> mp_if_c<false, T, E> is an alias for E. Otherwise, the result is a
>>> substitution failure."
>>>
>>> Should that read "mp_if_c<false, T, E...>"? If not, why?
>>
>> No.
>>
>> The idea here is that mp_if_c can be used in two ways. One is
>> mp_if_c<Cond, T, E>, which gives either T or E depending on Cond. The
>> other is mp_if_c<Cond, T>, which is the same as std::enable_if_t<Cond,
>> T> - gives T when Cond, otherwise a substitution failure.
>>
>> So
>>
>> mp_if_c<true, T> is T
>> mp_if_c<true, T, E> is T
>> mp_if_c<false, T, E> is E
>>
>> Aliases can't be specialized, so it's not possible to implement just the
>> above, which is why it takes a parameter pack for E... and does
>>
>> mp_if_c<true, T, E...> is T
>> mp_if_c<false, T, E> is E
>>
>> which for the three cases we're interested in gives the results we need.
>
> Why not separate the two use case into two primitives? We usually want
> one or the other and different tools would make sense, at least for
> documenting purpose.
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost

_______________________________________________
Unsubscribe & other changes: http://
Vinnie Falco via Boost
2017-07-15 13:09:56 UTC
Permalink
On Sat, Jul 15, 2017 at 5:57 AM, Andrey Semashev via Boost
<***@lists.boost.org> wrote:
> Why not separate the two use case into two primitives? We usually want one
> or the other and different tools would make sense, at least for documenting
> purpose.

Now that its been explained, I appreciate that `mp_if_c` has
additional functionality. I think its a mistake to split it up when it
is so elegantly expressed in its current form. I just wish there was
more explanation in the reference for a novice such as myself.

Thanks

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Peter Dimov via Boost
2017-07-15 13:11:57 UTC
Permalink
Andrey Semashev wrote:

> > The idea here is that mp_if_c can be used in two ways. One is
> > mp_if_c<Cond, T, E>, which gives either T or E depending on Cond. The
> > other is mp_if_c<Cond, T>, which is the same as std::enable_if_t<Cond,
> > T> - gives T when Cond, otherwise a substitution failure.
...

> Why not separate the two use case into two primitives? We usually want one
> or the other and different tools would make sense, at least for
> documenting purpose.

One could go either way on that, I suppose. It makes sense because mp_if<C,
T, E> gives you T when C, otherwise E, and mp_if<C, T> gives you T when C,
otherwise <nothing>. "If C, T, otherwise, ..."


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Vinnie Falco via Boost
2017-07-15 15:01:39 UTC
Permalink
This is my review of the mp11 library.



I. DESIGN
---------

The design of the library is well organized and well thought out. The
rationale of prepending `mp_` to all identifiers makes sense and
results in less confusion. It lets lets you write

using namespace boost::mp11;

with little chance of stepping on anything in the enclosing namespace.
Function names are consistent with their run-time equivalents. The
decision to recognize almost any class template as a list is brilliant
and speaks to the power of the library to express ideas in flexible
and concise ways.



II. IMPLEMENTATION
------------------

I looked at each public header file. Its really amazing how C++11
allows the compact expression of metafunctions using parameter packs;
this is reflected in mp11's implementation. Many of the functions are
simple, intuitive one-liners. There are helpful comments such as this,
to aid users who get compilation errors:

<https://github.com/pdimov/mp11/blob/8e1d23b11f25c3864593b6fc5a8449306e17ea23/include/boost/mp11/list.hpp#L28>

Everything is `constexpr` where possible, and the author has
implemented straightforward optimizations to reduce compilation times
for the heavier functions, such as these:

<https://github.com/pdimov/mp11/blob/8e1d23b11f25c3864593b6fc5a8449306e17ea23/include/boost/mp11/detail/mp_count.hpp#L46>

<https://github.com/pdimov/mp11/blob/8e1d23b11f25c3864593b6fc5a8449306e17ea23/include/boost/mp11/detail/mp_append.hpp#L81>

A casual inspection of the source files should be enough to give any
potential user confidence in the quality of the library (assuming they
are somewhat familiar with the domain). The implementation is in sharp
contrast to the "template soup" I usually encounter when looking at
Boost source code. For example, here's Hana:

<https://github.com/boostorg/hana/blob/e507494b5f7f51026e8afa317b3ca2c058a4d290/include/boost/hana/any_of.hpp#L58>

and here's mp11

<https://github.com/pdimov/mp11/blob/8e1d23b11f25c3864593b6fc5a8449306e17ea23/include/boost/mp11/algorithm.hpp#L861>



III. DOCUMENTATION
------------------

The documentation is spartan and not for a beginner like me. There is
little explanation on many of the functions (most are single
sentences), and a dearth of examples. Most of the reference is a
laundry-list of valid expressions with minimal exposition. I found
this in a surprising contrast to the linked articles, which were
brilliantly written, engaging, informative, and exciting. The author
explained that more examples are coming for the reference items.

Here's an example of the disparity. The documentation for mp_all has a
lot of exposition relative to other reference items, and it includes a
good chunk of example code:

mp_all<T…>

mp_all<T…> is mp_true if mp_to_bool<U> is mp_true for all types U
in T…, mp_false otherwise. Same as mp_and, but does not perform
short-circuit evaluation. mp_and<mp_false, void> is mp_false, but
mp_all<mp_false, void> is an error because void does not have a
nested value. The upside is that mp_all is potentially faster and does
not mask substitution failures as mp_and does.

Code Example 62. mp_all behavior

<https://github.com/pdimov/mp11/blob/8e1d23b11f25c3864593b6fc5a8449306e17ea23/doc/mp11/function.adoc#mp_allt>

Now compare that with the documentation for mp_replace_at_c:

mp_replace_at_c<L, I, W>

Replaces the element of L at zero-based index I with W and returns
the result.

<https://github.com/pdimov/mp11/blob/8e1d23b11f25c3864593b6fc5a8449306e17ea23/doc/mp11/algorithm.adoc#mp_replace_at_cl-i-w>

I realize that seasoned metaprogrammers will likely have no trouble at
all understanding these terse descriptions and lack of examples but
they aren't doing beginners any favors.

There are things missing from the documentation that I would expect or
hope to find, as some of them may be important to potential users and
others are just good marketing which could help to revive the dying
Boost:

* Comparison to other libraries
- How is this different from Hana? MPL?

* Limits
- Which functions work with almost limitless type lists?
- Which functions might require care in the size of type lists?

* Speed
- Benchmarks. The doc could link to http://metaben.ch/
- Which functions might become slow?

The type list limits are compiler-dependent so exact numbers aren't
expected, but at least guidance for where someone might encounter
problems could be provided to aid in the inevitable troubleshooting.

In my opinion, the documentation under-sells the library, I think more
could be done to increase the conversion ratio (the fraction of users
who decide to use the library after reading the documentation). I can
see that metaprogramming gurus who read the Overview will immediately
see the advantage of allowing L to be any class template, but I rather
doubt that beginners will see that - this should be explained in a bit
more direct terms. Here's a rough draft with some sizzle:

"mp11 is easier to use than other metaprogramming libraries because
it leverages C++11 and allows the use of any class template to express
a type list. Programs that use mp11 over other libraries will be easier
to read, compile faster, and require fewer lines of code."



IV. PRACTICAL USE
-----------------

The library appears useful for its intended purpose. I looked through
my own code to find metafunctions that could be expressed using mp11
instead. The result of this work can be found here:

<https://github.com/vinniefalco/Beast/tree/mp11>
<https://github.com/vinniefalco/Beast/commit/d0385e70fa45c675c617dcd192426e059bc7941d>

I stumbled a bit in the documentation trying to figure out how to form
my expressions but once I did the library performed wonderfully. I
liked how `mp_repeat_c` was a more general replacement of my
`repeat_tuple`.

I spent about two hours with it. Its a shame that so few of Beast's
metafunctions fell into the domain of problems that mp11 solves but
that's an issue with my library and not mp11. I am somewhat familiar
with the problem domain, having done some light manipulation of type
lists.



V. VERDICT
----------

I have seen various metaprogramming libraries over the years, such as
MPL and Hana. Neither of them jumped out at me as something easy to
use or immediately helpful. Despite all of my aforementioned
complaints regarding the documentation, mp11 remains the ONLY
metaprogramming library I have ever had success at in applying to my
own programs, and the only metaprogramming library I would consider
taking as a dependency.

For this reason, mp11 should be ACCEPTED.

Thanks

_______________________________________________
Unsubscribe & other changes: h
Louis Dionne via Boost
2017-07-24 02:57:05 UTC
Permalink
> A casual inspection of the source files should be enough to give any
> potential user confidence in the quality of the library (assuming they
> are somewhat familiar with the domain). The implementation is in sharp
> contrast to the "template soup" I usually encounter when looking at
> Boost source code. For example, here's Hana:
>
> &lt;https://github.com/boostorg/hana/blob/e507494b5f7f51026e8afa317b3ca2c058a4d290/include/boost/hana/any_of.hpp#L58&gt;
>
> and here's mp11
>
> &lt;https://github.com/pdimov/mp11/blob/8e1d23b11f25c3864593b6fc5a8449306e17ea23/include/boost/mp11/algorithm.hpp#L861&gt;

That's because they do significantly different things and pose significantly
different constraints on input the types. Hana's any_of is short-circuiting,
works on compile-time infinite sequences, and works on runtime values as
well as compile-time values. mp11 has none of that (because that's out of
scope for the library, except for short-circuiting which I was surprised
it did not provide).

Louis




--
View this message in context: http://boost.2283326.n4.nabble.com/review-mp11-Formal-review-of-Mp11-tp4696839p4697319.html
Sent from the Boost - Dev mailing list archive at Nabble.com.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Joaquin M López Muñoz via Boost
2017-07-16 22:22:09 UTC
Permalink
This is my review of Mp11. As I see it, an important use niche for this
library is to
allow for phasing out of Boost.MPL in C++11 compilers, so my review is
heavily biased by
this perspective.

To get acquainted with the lib, I made the little experiment of porting
Boost.MultiIndex
from Boost.MPL to Mp11 , results can be seen at:

https://github.com/joaquintides/multi_index_mp11
https://github.com/joaquintides/multi_index_mp11/commit/91f2b32cf5a27b3aeaaf6ceb42959c677410f490

The process was relatively straightforward, 9x% of it was boilerplate
substitution of the
form s/[typename] mpl::xx<...>::type/mp11::mp_xx<...>. As for the rest,
no serious problem
was found. Compile times dropped slightly, maybe around 5-10%, but I
did't measure
rigurously.

1 DESIGN

Mp11 makes the very sensible choice of coding metafunctions/type lists
as (variadic)
class/alias templates. From this principle everything else follows quite
naturally. I also
commend dispensing with Boost.MPL iterators and using indexes instead.

1.1 I really don't like the mp_ prefix. I understand this is meant to
minimize clashes when
using namespace::mp11, but the same purpose can be served by simply
using namespace mp=boost::mp11. Having to add this pesky mp_ thing
always got in the
way of seamless porting, for no real benefit. To add more confusion,
some functions
(those in integer_sequence.hpp and tuple.hpp) don't have the prefix.

1.2 Why are quoted metafunctions codified with a fn member rather than
Boost.MPL-honored
apply? Why call it quoted metafunctions rather than metafunction
classes, as Boost.MPL
does?

1.3 I find that these metafunctions are missing/misplaced:
pop_back
at/at_c (should be in list.hpp)
insert/insert_c/erase/erase_c (should be in list.hpp)
replace_at/replace_at_c
clear (should be in list.hpp)

1.4 Tuple operations are named differently from their C++14/17
counterparts to
"avoid ambiguities when both are visible or in unqualified calls". Yet,
this policy is not
followed in integer_sequence.hpp. I'd rather go the latter way.

1.5 Treatment of sets and maps is very dissimilar. Why mp_map_find but no
mp_set_find? Why mp_set_push_(back|front) but no mp_map_push_(back|front)?
Why mp_map_erase but no mp_set_erase? I think both interfaces should
have the
same functions, except possibly mp_map_(replace|update).

1.5.1 I think that, for consistency, mp_map_find should return an index
(like mp_find) rather than the element or void.

1.6 Boost.MPL sequences simulate variadic behavior by having
boost::mpl::na-defaulted
type parameters. As a consequence, the following is somehow unexpected:

std::cout<<mp_size<boost::mpl::vector<int,char>>::value<<"\n"; //prints 20

Porting from / coexisting with Boost.MPL would be greatly aided by some
utility
function to convert Boost.MPL sequences to Mp11 lists:

template<typename MplSequence>
struct mp_mpl_sequence_impl;

template<template<typename...> class M,typename... T>
struct mp_mpl_sequence_impl<M<T...>>
{
using type=mp_remove<mp_list<T...>,boost::mpl::na>;
};

template<typename MplSequence>
using mp_mpl_sequence=typename mp_mpl_sequence_impl<MplSequence>::type;

...

std::cout<<mp_size<
mp_mpl_sequence<boost::mpl::vector<int,char>>>::value<<"\n"; // prints 2

1.7 mp_eval[_xx] functions should accept metafunctions in both their
true and false
branches. As it stands now, we'd have to write stuff like

using l1=mp_if_c<
b,
mp_list<mp_quote<F>,type1,type2>,
mp_list<mp_quote<G>,type3,type4>>;
using l2=mp_apply_q<mp_first<l1>,mp_rest<l1>>;

to emulate (the as of yet non-existent)

using l2=mp_eval_if_c<b,F,type1,type2,G,type3,type4>;

The current behavior would be served by the new interface with little
overhead:

(current) mp_eval_if_c<b,T,F,U...>
(new) mp_eval_if_c<b,mp_identity_t,T,F,U...>

I have to say I don't know how to apply this new behavior to mp_eval_if_q;
thinking out loud, we'd need something like

mp_eval_if_q<B,Q1,U1...,mp_else,Q2,U2...>

which doesn't look too pretty. A more exotic alternative could be

mp_eval_if_q<B,Q1(U1...),Q2(U2...)>

1.7.1 Why there's no eval_if_q_c (or eval_if_c_q?)

2 IMPLEMENTATION

I had just a cursory look at the code, but everything seems clean and
reasonably
straightforward. I like the fact that C++14/17 features are taken
advantage of when
available (e.g. variadic fold expressions). There are many lines wider
than 80
chars, but I think this is OK with current Boost guidelines.

Testing seems pretty exhaustive. I find it surprising that there's so much
boilerplate code repetition in the testing code --I'd have expected Mp11
itself to
be used to generate extensive test cases automatically.

3 DOCUMENTATION

This is IMHO the weakest part of this submission. I have concerns with
both the
tutorial and the reference.

3.1 TUTORIAL

With template metaprogramming, one has to ask whether a tutorial for a
metaprogamming lib should be oriented towards explaining *metaprogramming*
or rather the particular design of the library. Mp11 documentation seems to
try both ways, and does not excel in either of them.

3.1.1 Examples are heavy handed and do not focus on why Mp11 is useful
--too much
discussion goes into the particular difficulties of the use cases
studied. I consider
myself a reasonably advanced metaprogrammer and found it difficult (and,
ultimately,
useless) to follow the exposition. For a newbie, the examples are just
impenetrable; for
a seasoned metaprogrammer wanting to learn Mp11, she's better off
reading the
definitions section only and then jumping into the reference. I suggest
taking a look
at Brigand tutorials, which are excellent at explaining the lib to
entry-level
metaprogrammers in a step-by-step fashion. I think the key is Brigand
tutorials
don't try to tackle industry-grade metaprogramming problems: they just
accompany
the reader along toy use cases, and that's really enough.

3.1.2 The definitions section, by contrast, is too terse and at points
vague to the
verge of incorrection:

- It is not "template class" but "class template".
- It is not made clear whether a list is a class/alias template (say,
mp_list) or
rather an instantiation of this template (mp_list<int,char>). Same
goes for
metafunctions. The confusion extends to the reference, where class
templates and
their instantiations are named the same, for instance:

template<class L> using mp_reverse = /*...*/;
mp_reverse<L<T1, T2, …​, Tn>> is L<Tn, …​, T2, T1>.

- The above is not a legal subtlety: as it stands, the definition for
set doesn't
make sense, as it implies that a set is a *class template* that somehow
enforces unicity of template type parameters. Same goes for maps.
- All in all, seems like the author's intention is to define lists
(and sets and maps)
as *template class instantiations*: if this is the case then it has
to be explained
how two different lists (say, the result of pushing back a type to a
list) are connected
through their common class template.
- By contrast, seems like the intention is to define a metafunction as a
class/alias template rather than its instantiations (e.g. mp_size is
a metafunction
but mp_size<my_list> is not). If this is the case, then the assertion
that

"Another distinguishing feature of this approach is that lists
(L<T…​>) have the
same form as metafunctions (F<T…​>) and can therefore be used as such."

is false.
- There's a latent concept that goes undocumented, namely lists resulting
from the instantiation of a non-variadic class/alias template (e.g.
std::pair). Some
Mp11 metafunctions are not applicable to them (e.g. mp_push_back),
but this
is not clearly documented.

To be clear, I'm not advocating mathematical rigor, but the current
fuzziness is
confusing at best and can impede understanding at worst.

3.2 REFERENCE

In general, the reference is too terse and overlooks important details.

3.2.1 A "Requires" clause should be added to many entries. For example,
it is not clear what happens with mp_at_c<L, I> when I is out of bounds
(it does not compile). Another example: mp_pop_front<std::pair<int,bool>>
does not compile because std::pair<int,bool> is not a "variadic sequence"
(missing concept here).

3.2.2 A complexity section should be added, where complexity is number of
of template instantiations. For instance, I don't know how costly set
operations
are.

3.3 PERFORMANCE

As already suggested in another review, links to metaben.ch could be added.

4 WHY ANOTHER METAPROGRAMMING LIBRARY?

The landscape of C++ metaprogramming libs is quite populated. These libs
can be classified into (to follow metaben.ch's terminology) heterogeneous
(Boost.Fusion, Boost.Hana) and pure-type (Boost.MPL, Mp11, Brigand, Metal,
Kvasir). To be fair, we're dealing here with acceptance of a library
into Boost,
so we should only be really concerned about intra-Boost clashes, which
leaves
us with Boost.Fusion, Boost.Hana, Boost.MPL and Mp11. In my opinion,
heterogeneous and pure-type libs have different scopes and entry barriers:
for the kind of intra-lib scaffolding I find myself doing, I'd rather go
with
a pure-type metaprogramming lib before buying the complexities of
Boost.Hana.
In this respect, a replacement for old and clunky Boost.MPL is most welcome,
and this is the place that Mp11 can occupy.

This said, we can also look out to the wider world and recognize that
Mp11 and
Brigand have the very same design philosophy and come up with solutions
that are exactly interchangeable. It would be great if we could find a
way that
efforts behind Mp11 and Brigand could be coordinated to come up with
something bigger that could serve as Boost's pure-type metaprogramming
library
as well as a non-Boost lib. To be honest, I don't have a clue how this
could be
done, or whether there's willingness to collaborate among Mp11's and
Brigand's authors.

5 ANSWERS TO REVIEW QUESTIONS

* Should Mp11 be accepted into Boost? Please state all conditions for
acceptance
explicity.

My vote is for CONDITIONAL ACCEPTANCE dependent upon proper addressing of,
at least,

mp_list<_1_1, _1_2, _1_4, _1_5, _1_7, _3_1_2, _3_2_1>

Of course I'd like all points of my review to be discussed, but I feel
only those listed
above are important enough to hold acceptance.

* What is your evaluation of the design?
* What is your evaluation of the implementation?
* What is your evaluation of the documentation?
* What is your evaluation of the potential usefulness of the library?

All addressed above, hopefully.

* Did you try to use the library? With what compiler? Did you have any
problems?

Yes. VS 2015. No problems.

* How much effort did you put into your evaluation? A glance? A quick
reading?
In-depth study?

5-6 hours for the porting exercise, 4-5 hours for the review.

* Are you knowledgeable about the problem domain?

I've been metaprogramming for 14 years.

Thanks to Peter Dimov for his submission of Mp11 and for being such an
active
contributor to Boost during so many years.

Joaquín M López Muñoz

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo
Peter Dimov via Boost
2017-07-16 23:06:22 UTC
Permalink
Joaquin M López Muñoz wrote:

> 1.1 I really don't like the mp_ prefix. I understand this is meant to
> minimize clashes when using namespace::mp11, but the same purpose can be
> served by simply using namespace mp=boost::mp11.

Well... it's also meant to make it possible to move mp11 into std without
changes. :-)

> 1.3 I find that these metafunctions are missing/misplaced:
> pop_back

pop_back is not provided for the same reason std::vector doesn't provide
pop_front - it's much less efficient than its siblings, and providing it
could mislead people into thinking that it's equally efficient.

> at/at_c (should be in list.hpp)
> insert/insert_c/erase/erase_c (should be in list.hpp)
> replace_at/replace_at_c

The partitioning is roughly based on whether the operation can be trivially
expressed (f.ex. mp_second<L<T1, T2, T...>> -> T2), or requires a more
elaborate implementation (as all primitives taking an arbitrary index
require.)

> clear (should be in list.hpp)

mp_clear could be in list, yes.

> 1.5 Treatment of sets and maps is very dissimilar. Why mp_map_find but no
> mp_set_find? Why mp_set_push_(back|front) but no mp_map_push_(back|front)?
> Why mp_map_erase but no mp_set_erase? I think both interfaces should have
> the same functions, except possibly mp_map_(replace|update).

Set operations are only provided for the cases where the generic list-based
algorithm would be unsuitable or less efficient.

> Porting from / coexisting with Boost.MPL would be greatly aided by some
> utility function to convert Boost.MPL sequences to Mp11 lists:

...

This unfortunately doesn't work in general - as Bruno Dutra explained to
me - because MPL operations on, f.ex. mpl::vector, do not necessarily return
an mpl::vector.

> 1.7.1 Why there's no eval_if_q_c (or eval_if_c_q?)

The purpose of the _q forms is twofold; one, to enable passing a quoted
metafunction, and two, to be metafunctions themselves (that is, they only
take type parameters.) _c_q would meet the first goal but not the second.
This by itself does not preclude its inclusion, but, while the ability to
omit ::value is convenient, it's not indispensable.

> - It is not "template class" but "class template".

Yes, it's actually "template class", meaning a class template instantiation.
A template class is a class; a class template is a template. Too subtle,
perhaps, but this is correct terminology.

> 3.2.1 A "Requires" clause should be added to many entries.

That's correct. I'll be nailing the requirements down one by one. The choice
in each case is between a hard error and a substitution failure, and it is
not a trivial choice. (Although Bruno would disagree. :-) )

Thank you for the review!


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listi
Joaquin M López Muñoz via Boost
2017-07-17 07:40:56 UTC
Permalink
El 17/07/2017 a las 1:06, Peter Dimov via Boost escribió:
> Joaquin M López Muñoz wrote:
>
>> 1.1 I really don't like the mp_ prefix. I understand this is meant to
>> minimize clashes
>> when using namespace::mp11, but the same purpose can be served by simply
>> using namespace mp=boost::mp11.
>
> Well... it's also meant to make it possible to move mp11 into std
> without changes. :-)

We already have subnamespaces in std (e.g. std::chrono), so your
standardization plan could
be realized as s/boost/std.

> 1.3 I find that these metafunctions are missing/misplaced:
>> pop_back
>
> pop_back is not provided for the same reason std::vector doesn't
> provide pop_front - it's
> much less efficient than its siblings, and providing it could mislead
> people into thinking that
> it's equally efficient.

Understood.

>> at/at_c (should be in list.hpp)
>> insert/insert_c/erase/erase_c (should be in list.hpp)
>> replace_at/replace_at_c
>
> The partitioning is roughly based on whether the operation can be
> trivially expressed
> (f.ex. mp_second<L<T1, T2, T...>> -> T2), or requires a more elaborate
> implementation
> (as all primitives taking an arbitrary index require.)

I see. My assumption was that list.hpp would contain mp equivalents for
std container
member functions, while algorithm.hpp was home to mp translations of
<algorithm> functions. Maybe an intro for each header in the reference
can help
orient readers.

> [...]
>
>> 1.5 Treatment of sets and maps is very dissimilar. Why mp_map_find but no
>> mp_set_find? Why mp_set_push_(back|front) but no
>> mp_map_push_(back|front)?
>> Why mp_map_erase but no mp_set_erase? I think both interfaces should
>> have
>> the same functions, except possibly mp_map_(replace|update).
>
> Set operations are only provided for the cases where the generic
> list-based algorithm
> would be unsuitable or less efficient.

I'm not sure this observation entirely addresses my question.

* mp_set_find is not provided because mp_find does the job --OK, but
consider my
point 1.5.1 then.
* If mp_set_push_(back|front) is provided (no suitable list-based
algorithm), why not
mp_map_push_(back|front)?

>> Porting from / coexisting with Boost.MPL would be greatly aided by
>> some utility
>> function to convert Boost.MPL sequences to Mp11 lists:
>
> ...
>
> This unfortunately doesn't work in general - as Bruno Dutra explained
> to me - because
> MPL operations on, f.ex. mpl::vector, do not necessarily return an
> mpl::vector.

Something more generic can be provided

struct mp_mpl_sequence_folder
{
template<typename T,typename L>
struct apply{using type=mp_push_front<T,L>;};
};

template<typename MplSequence>
struct mp_mpl_sequence_impl:boost::mpl::reverse_fold<
MplSequence,
mp_list<>,
mp_mpl_sequence_folder
>{};

template<typename MplSequence>
using mp_mpl_sequence=typename mp_mpl_sequence_impl<MplSequence>::type;

with faster specializations for boost::mpl::vector and other MPL sequences.

> [...]
>
>> - It is not "template class" but "class template".
>
> Yes, it's actually "template class", meaning a class template
> instantiation. A template
> class is a class; a class template is a template. Too subtle, perhaps,
> but this is correct
> terminology.

I fail to see "template class" defined in N4296 (one ocurrence only in
[sequences.general],
and seems an editorial typo as it obviously refers to class templates,
and a handful of
ocurrences of "non-template class"). Additionally:

* "A metafunction is a class template or a template alias [...]":
s/"template alias"/"alias template"?
* "mp_unique<L> returns a list of the same type as L [...]": being "the
same type" needs
definition. This is found in other places throughout the documentation.

Joaquín M López Muñoz

_______________________________________________
Unsubscribe & other changes: http://lists.boost.or
Peter Dimov via Boost
2017-07-17 10:20:39 UTC
Permalink
Joaquin M López Muñoz wrote:
> El 17/07/2017 a las 1:06, Peter Dimov via Boost escribió:
> > > Joaquin M López Muñoz wrote:
> > >
> > >> 1.1 I really don't like the mp_ prefix. I understand this is meant to
> > >> minimize clashes when using namespace::mp11, but the same purpose can
> > >> be served by simply using namespace mp=boost::mp11.
> >
> > Well... it's also meant to make it possible to move mp11 into std
> > without changes. :-)
>
> We already have subnamespaces in std (e.g. std::chrono), so your
> standardization plan could be realized as s/boost/std.

It could if I wanted to propose std::mp::if_, but I don't. I want to propose
std::mp_if.

I know that this makes the library more difficult to use in other Boost
libraries where there's no convenient place to put the using directive. :-/

> > Set operations are only provided for the cases where the generic
> > list-based algorithm would be unsuitable or less efficient.
>
> I'm not sure this observation entirely addresses my question.
>
> * mp_set_find is not provided because mp_find does the job --OK, but
> consider my point 1.5.1 then.
> * If mp_set_push_(back|front) is provided (no suitable list-based
> algorithm), why not mp_map_push_back|front)?

Our disagreement here rests on whether set should be the same as map. I do
not view them the same at all. Set is a list with an added constraint, but
it's still a list, and list-like things can be done to it. It's lower level,
so order matters. Map is a higher-level key-based structure, where order
doesn't matter (logically.)

> Something more generic can be provided
>
> struct mp_mpl_sequence_folder

It can, but it ties me to MPL, so I've chosen not to provide it.

> Additionally:
>
> * "A metafunction is a class template or a template alias [...]":
> s/"template alias"/"alias template"?
> * "mp_unique<L> returns a list of the same type as L [...]": being "the
> same type" needs definition. This is found in other places throughout the
> documentation.

You're right, the documentation is not particularly rigorous. I use C++
terms here and the colloquial meaning of "type" there.

I tend to think that the meaning is more or less clear, but things could be
tightened up at the expense of terseness.


_______________________________________________
Unsubscribe & other ch
Peter Dimov via Boost
2017-07-17 11:05:02 UTC
Permalink
> > We already have subnamespaces in std (e.g. std::chrono), so your
> > standardization plan could be realized as s/boost/std.
>
> It could if I wanted to propose std::mp::if_, but I don't. I want to
> propose std::mp_if.
>
> I know that this makes the library more difficult to use in other Boost
> libraries where there's no convenient place to put the using directive.
> :-/

To expand on this a bit:

There are, in general, two main modes of use of Mp11, serving two audiences.
One is the "easy mode", where one includes <boost/mp11.hpp>, combines that
with `using namespace boost::mp11;`, then goes ahead using mp_this and
mp_that without qualification. This serves (a) people who play with
metaprogramming in short test cases, (b) people who have a need for a
metaprogram in a .cpp file (or an internal header file not meant for public
consumption), whether library or application one.

Mode two is in use in header-only libraries. There the library author is
generally reluctant to employ the using directive, which forces the
comparatively awkward mp11::mp_this style.

I realize that my choice gives preference to case one at the expense of case
two.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Joaquin M López Muñoz via Boost
2017-07-17 11:32:05 UTC
Permalink
El 17/07/2017 a las 13:05, Peter Dimov via Boost escribió:
>
> To expand on this a bit:
>
> There are, in general, two main modes of use of Mp11, serving two
> audiences.
> One is the "easy mode", where one includes <boost/mp11.hpp>, combines that
> with `using namespace boost::mp11;`, then goes ahead using mp_this and
> mp_that
> without qualification. This serves (a) people who play with
> metaprogramming
> in short test cases, (b) people who have a need for a metaprogram in a
> .cpp file
> (or an internal header file not meant for public consumption), whether
> library or
> application one.

These people would be equally served by instructing them to

namespace mp=boost::mp11;

and then go ahead with mp::this and mp::that.

Joaquín M López Muñoz

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Joaquin M López Muñoz via Boost
2017-07-17 11:06:44 UTC
Permalink
El 17/07/2017 a las 12:20, Peter Dimov via Boost escribió:
> Joaquin M López Muñoz wrote:
>> El 17/07/2017 a las 1:06, Peter Dimov via Boost escribió:
>> > > Joaquin M López Muñoz wrote:
>> > >
>> > >> 1.1 I really don't like the mp_ prefix. [...]
>> >
>> > Well... it's also meant to make it possible to move mp11 into std >
>> without changes. :-)
>>
>> We already have subnamespaces in std (e.g. std::chrono), so your
>> standardization
>> plan could be realized as s/boost/std.
>
> It could if I wanted to propose std::mp::if_, but I don't. I want to
> propose std::mp_if.
>
> I know that this makes the library more difficult to use in other
> Boost libraries where
> there's no convenient place to put the using directive. :-/

As I see it, users of your library can be divided into three targets:

1. Regular users of Boost.
2. Boost authors (like myself).
3. Users of the std library, once this is proposed to the committee,
accepted and implemented.

My personal opinion is that 1 should be given priority, followed by 2
and, at a distance, 3.
It is a submission for Boost we're dealing here with. In that light, mp_
sounds like noise
to me (also for 3, but this is not a subject for this review).

> [...]
>
> Our disagreement here rests on whether set should be the same as map.
> I do not view
> them the same at all. Set is a list with an added constraint, but it's
> still a list, and list-like
> things can be done to it. It's lower level, so order matters. Map is a
> higher-level
> key-based structure, where order doesn't matter (logically.)

Totally valid point of view. My intuition about mp11::map comes from the
definition
("a list of lists [...]") and the std::set/std::map analogy. If you want
to pull readers away
from that mindset you might want to be a little more descriptive about
what a map is
meant to be / be used for, and/or change the name to something not
semantically
overloaded like, say, "dictionary".

>> Something more generic can be provided
>>
>> struct mp_mpl_sequence_folder
>
> It can, but it ties me to MPL, so I've chosen not to provide it.

This can be confined to a dedicated header, so that the rest of Mp11 is
MPL-free and your
planned std proposal won't be polluted, and you'd be providing a service
to potential
users willing to migrate from Boost.MPL but wanting to do so in a
progressive manner.

Joaquín M López Muñoz

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mail
Bjorn Reese via Boost
2017-07-22 09:23:06 UTC
Permalink
On 07/17/2017 01:06 PM, Joaquin M López Muñoz via Boost wrote:

> My personal opinion is that 1 should be given priority, followed by 2
> and, at a distance, 3.
> It is a submission for Boost we're dealing here with. In that light, mp_
> sounds like noise
> to me (also for 3, but this is not a subject for this review).

The main problem is that some names would collide with C++ keywords. A
quick scan of the documentation reveal these possible conflicts: bool,
true, false, int, if, and void.

I am wondering if there is an alternative solution to the mp_ prefix
and the MPL-style _ suffix.

For instance, type-traits have faced the same problem and selected
synonyms, e.g. std::conditional instead of if, or longer names, e.g.
true_type and false_type.

Would that be a feasible approach?

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listin
Joaquin M López Muñoz via Boost
2017-07-22 09:35:52 UTC
Permalink
El 22/07/2017 a las 11:23, Bjorn Reese via Boost escribió:
> On 07/17/2017 01:06 PM, Joaquin M López Muñoz via Boost wrote:
>
>> My personal opinion is that 1 should be given priority, followed by 2
>> and, at a distance, 3.
>> It is a submission for Boost we're dealing here with. In that light,
>> mp_ sounds like noise
>> to me (also for 3, but this is not a subject for this review).
>
> The main problem is that some names would collide with C++ keywords. A
> quick scan of the documentation reveal these possible conflicts: bool,
> true, false, int, if, and void.
>
> I am wondering if there is an alternative solution to the mp_ prefix
> and the MPL-style _ suffix.

Besides prefixing and suffixing, the only reamining alternative is using
another name,
of course.

> For instance, type-traits have faced the same problem and selected
> synonyms, e.g. std::conditional instead of if, or longer names, e.g.
> true_type and false_type.

Personally, I like MPL-style suffixing better: it's a sort of tradition
within Boost
(boost::hana::and_, boost::proto::if_, boost::msm::front::euml::while_),
name
intent is clear and seems to me the _ suffix it's automatically parsed
out by the
(trained) human eye.

Joaquín M López Muñoz

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/bo
Peter Dimov via Boost
2017-07-17 21:03:13 UTC
Permalink
Joaquin M López Muñoz wrote:
> Something more generic can be provided
>
> struct mp_mpl_sequence_folder
> {
> template<typename T,typename L>
> struct apply{using type=mp_push_front<T,L>;};
> };
>
> template<typename MplSequence>
> struct mp_mpl_sequence_impl:boost::mpl::reverse_fold<
> MplSequence,
> mp_list<>,
> mp_mpl_sequence_folder
> >{};
>
> template<typename MplSequence>
> using mp_mpl_sequence=typename mp_mpl_sequence_impl<MplSequence>::type;

How about we provide it in MPL instead?

namespace mpl {

template<class Seq, template<class...> class L = std::tuple> using to_tuple
= /*as above*/

}

to_tuple subject to bikeshedding (to_variadic? as_variadic_sequence?).


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi
Joaquin M López Muñoz via Boost
2017-07-18 07:58:19 UTC
Permalink
El 17/07/2017 a las 23:03, Peter Dimov via Boost escribió:
> Joaquin M López Muñoz wrote:
>> Something more generic can be provided
>>
>> [...]
>>
>> template<typename MplSequence>
>> using mp_mpl_sequence=typename
>> mp_mpl_sequence_impl<MplSequence>::type;
>
> How about we provide it in MPL instead?
>
> namespace mpl {
>
> template<class Seq, template<class...> class L = std::tuple> using
> to_tuple = /*as above*/
>
> }
>
> to_tuple subject to bikeshedding (to_variadic? as_variadic_sequence?).

Well, I guess users don't care where the utility belongs as long as it's
documented and available
somewhere. If you want to integrate with MPL nicely, this probably
should take the form of a
variadic sequence inserter
(http://www.boost.org/libs/mpl/doc/refmanual/inserter.html ).
Something like:

struct variadic_inserter_op
{
template<template<typename...> class L,typename... Ts,typename T>
static L<Ts...,T> helper(L<Ts...>,T);

template<typename L,typename T>
struct apply
{
using type=decltype(helper(std::declval<L>(),std::declval<T>()));
};
};

template<template <typename...> class L>
struct
variadic_inserter:boost::mpl::inserter<L<>,variadic_inserter_op>{};

template<class Seq,template<typename...> class L=std::tuple>
using to_variadic_sequence=boost::mpl::copy<Seq,variadic_inserter<L>>;

Note that this would be the only C++11 piece of code in Boost.MPL.

Joaquín M López Muñoz




_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cg
Bruno Dutra via Boost
2017-07-18 10:28:37 UTC
Permalink
On Tue, Jul 18, 2017 at 9:58 AM, Joaquin M López Muñoz via Boost <
***@lists.boost.org> wrote:

> El 17/07/2017 a las 23:03, Peter Dimov via Boost escribió:
>
>> Joaquin M López Muñoz wrote:
>>
>>> Something more generic can be provided
>>>
>>> [...]
>>>
>>> template<typename MplSequence>
>>> using mp_mpl_sequence=typename mp_mpl_sequence_impl<MplSequen
>>> ce>::type;
>>>
>>
>> How about we provide it in MPL instead?
>>
>> namespace mpl {
>>
>> template<class Seq, template<class...> class L = std::tuple> using
>> to_tuple = /*as above*/
>>
>> }
>>
>> to_tuple subject to bikeshedding (to_variadic? as_variadic_sequence?).
>
>
Personally I think this doesn't belong to MPL.

Actually I suggest providing a slightly more general utility that not
only converts MPL Sequences, but Metafunction Classes as well and also in a
recursive fashion, that is, Sequences of Sequences would be converted to
variadic Lists of variadic Lists for example.

Metal used to provide such a utility up until recently, when I decided to
remove it, but maybe it can still serve as a source of inspiration [1].
Some usage examples are available as well [2].

[1]:
https://github.com/brunocodutra/metal/blob/85d6d32f6e58e648c4573189f8bf2d7633604f27/include/metal/external/mpl.hpp
[2]:
https://github.com/brunocodutra/metal/blob/85d6d32f6e58e648c4573189f8bf2d7633604f27/example/src/mpl.cpp#L10

Bruno

_______________________________________________
Unsubscribe & other changes: http://li
Peter Dimov via Boost
2017-07-18 10:51:55 UTC
Permalink
Bruno Dutra wrote:

> >> How about we provide it in MPL instead?
> >>
> >> namespace mpl {
> >>
> >> template<class Seq, template<class...> class L = std::tuple> using
> >> to_tuple = /*as above*/
> >>
> >> }
...

> Personally I think this doesn't belong to MPL.

A cursory search seems to show that the desire to use std::tuple with MPL is
not uncommon, although getting a tuple out of an MPL sequence is of course
only half of the story, people also want to use std::tuple as if it were an
MPL sequence.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Peter Dimov via Boost
2017-07-18 13:51:28 UTC
Permalink
> > Personally I think this doesn't belong to MPL.
>
> A cursory search seems to show that the desire to use std::tuple with MPL
> is not uncommon, although getting a tuple out of an MPL sequence is of
> course only half of the story, people also want to use std::tuple as if it
> were an MPL sequence.

I've decided to provide the latter instead. That is, upon inclusion of
<boost/mp11/mpl.hpp>, both mp_list and std::tuple become MPL sequences and
can be manipulated with MPL algorithms. This implies the ability to convert
an arbitrary MPL sequence into an mp_list or std::tuple, via mpl::copy<Seq,
mpl::back_inserter<mp_list<>>>::type.

https://github.com/pdimov/mp11/blob/feature/mpl/include/boost/mp11/mpl.hpp
https://github.com/pdimov/mp11/blob/feature/mpl/test/mpl.cpp


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Joaquin M López Muñoz via Boost
2017-07-18 21:52:44 UTC
Permalink
El 18/07/2017 a las 15:51, Peter Dimov via Boost escribió:
>> > Personally I think this doesn't belong to MPL.
>>
>> A cursory search seems to show that the desire to use std::tuple with
>> MPL is not uncommon,
>> although getting a tuple out of an MPL sequence is of course only
>> half of the story, people
>> also want to use std::tuple as if it were an MPL sequence.
>
> I've decided to provide the latter instead. That is, upon inclusion of
> <boost/mp11/mpl.hpp>, both
> mp_list and std::tuple become MPL sequences and can be manipulated
> with MPL algorithms.

This looks cool. Thank you!

Joaquín M López Muñoz

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Bruno Dutra via Boost
2017-07-17 11:47:27 UTC
Permalink
On Mon, Jul 17, 2017 at 1:06 AM, Peter Dimov via Boost <
***@lists.boost.org> wrote:

> Joaquin M López Muñoz wrote:
>
>> Porting from / coexisting with Boost.MPL would be greatly aided by some
>> utility function to convert Boost.MPL sequences to Mp11 lists:
>>
>
> ...
>
> This unfortunately doesn't work in general - as Bruno Dutra explained to
> me - because MPL operations on, f.ex. mpl::vector, do not necessarily
> return an mpl::vector.


This reads backwards to me.

It's true that the signature (i.e. types) of Boost.MPL containers are left
unspecified and, indeed, on some platforms mpl::vector is implemented via
inheritance through opaque proxy types, but that only means one can't
simply rely on the property that any instance of a variadic template class
is a List to advertise seamless interoperation with Boost.MPL, which is
also aggravated by the fact it emulates variadic parameters packs via
default template arguments.

The alternative, which seems to be what Joaquin proposes here, is to
provide a utility metafunction that explicitly converts from Boost.MPL
containers into variadic Lists and one simple way of doing it is to use
mpl::fold to push the elements of Boost.MPL containers one by one into a
variadic List by means of a custom Metafunction Class in the Boost.MPL
sense.

Bruno

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/l
Peter Dimov via Boost
2017-07-16 23:24:41 UTC
Permalink
Joaquin M López Muñoz wrote:

> 1.7 mp_eval[_xx] functions should accept metafunctions in both their true
> and false branches.

I can't make this work.

#include <type_traits>
#include <tuple>

template<bool C, template<class...> class F, class... T, template<class...>
class G, class... U> using eval_if = void;

int main()
{
using R = eval_if<true, std::tuple, int, float, std::tuple, void>;
}

prog.cc:4:55: error: template parameter pack must be the last template
parameter
template<bool C, template<class...> class F, class... T, template<class...>
class G, class... U> using eval_if = void;
^

One might argue that it ought to work because G would obviously terminate
the first pack, but it doesn't. :-)

mp_eval_if_c<cond, mp_eval_if_c<!cond, void, F, T...>, G, U...> is not
pretty but... it works.

There's also the option of typename mp_if_c<cond, mp_defer<F, T...>,
mp_defer<G, U...>>::type.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/li
Joaquin M López Muñoz via Boost
2017-07-17 08:17:09 UTC
Permalink
El 17/07/2017 a las 1:24, Peter Dimov via Boost escribió:
> Joaquin M López Muñoz wrote:
>
>> 1.7 mp_eval[_xx] functions should accept metafunctions in both their
>> true and
>> false branches.
>
> I can't make this work. [...]

This is most unfortunate. My original concern remains though that there's no
reason why one of the two branches of mp_eval_if should not accept a
metafunction
(and note the irony that mp_eval_if<B,...> precisely does not eval when
B holds). If
syntax can't be made to work, it could be advisable to drop mp_eval_if
altogether and provide for instance mp_apply_if:

mp_apply_if<B,F,mp_list<T...>,G,mp_list<U...>>

Joaquín M López Muñoz

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/
Peter Dimov via Boost
2017-07-17 09:58:44 UTC
Permalink
Joaquin M López Muñoz wrote:

> If syntax can't be made to work, it could be advisable to drop mp_eval_if
> altogether and provide for instance mp_apply_if:
>
> mp_apply_if<B,F,mp_list<T...>,G,mp_list<U...>>

Given that the one function formulation covers a significant majority of the
practical use cases, dropping it in favor of mp_apply_if would be a
significant regression in usability.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/lis
Peter Dimov via Boost
2017-07-16 23:52:55 UTC
Permalink
> > https://github.com/joaquintides/multi_index_mp11/commit/91f2b32cf5a27b3aeaaf6ceb42959c677410f490

> template<typename TagList> struct no_duplicate_tags { typedef
> mp11::mp_fold< TagList, mp11::mp_list<>, mp11::mp_set_push_back > aux;

This is mp_unique<TagList>, but...

> BOOST_STATIC_CONSTANT(
> bool,value=(mp11::mp_size<TagList>::value==mp11::mp_size<aux>::value)); };

... this in its entirety is what Metal calls "distinct", the counterpart to
mp_same<T...> that returns true not when all Ts are the same, but when all
Ts are distinct.

A good argument for adding mp_distinct (or the equivalent list-based
formulation mp_is_set), I suppose.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Peter Dimov via Boost
2017-07-17 01:11:05 UTC
Permalink
Joaquin M López Muñoz wrote:

> 1.4 Tuple operations are named differently from their C++14/17
> counterparts to "avoid ambiguities when both are visible or in unqualified
> calls". Yet, this policy is not followed in integer_sequence.hpp. I'd
> rather go the latter way.

The primitives in integer_sequence.hpp are template aliases, so
argument-dependent lookup does not apply to them. The tuple functions are,
well, functions, and when f.ex. make_from_tuple<T>(tp) is called with an
std::tuple, ADL finds std::make_from_tuple because std is an associated
namespace. So the code suddenly becomes ambiguous in C++17.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/list
Joaquin M López Muñoz via Boost
2017-07-17 08:32:02 UTC
Permalink
El 17/07/2017 a las 3:11, Peter Dimov via Boost escribió:
> Joaquin M López Muñoz wrote:
>
>> 1.4 Tuple operations are named differently from their C++14/17
>> counterparts to "avoid ambiguities when both are visible or in
>> unqualified calls". Yet, this policy is not followed in
>> integer_sequence.hpp. I'd rather go the latter way.
>
> The primitives in integer_sequence.hpp are template aliases, so
> argument-dependent lookup does not
> apply to them. The tuple functions are, well, functions, and when
> f.ex. make_from_tuple<T>(tp) is
> called with an std::tuple, ADL finds std::make_from_tuple because std
> is an associated namespace.
> So the code suddenly becomes ambiguous in C++17.

You can replace your implementation with using std::make_from_tuple when
the latter is available.
After all, the perceived intention of these functions is precisely to
serve as a substitute in wait for
C++17 to arrive.

Same goes for integer_sequence.hpp, even if the conditions for collision
are different.

Joaquín M López Muñoz

_______________________________________________
Unsubscribe & other changes: http://lists.boos
Peter Dimov via Boost
2017-07-17 09:54:42 UTC
Permalink
Joaquin M López Muñoz wrote:

> You can replace your implementation with using std::make_from_tuple when
> the latter is available.

You can still replace construct_from_tuple, you're just not forced to
because the code doesn't break.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/
Joaquin M López Muñoz via Boost
2017-07-17 11:22:24 UTC
Permalink
El 17/07/2017 a las 11:54, Peter Dimov via Boost escribió:
> Joaquin M López Muñoz wrote:
>
>> You can replace your implementation with using std::make_from_tuple
>> when the latter is available.
>
> You can still replace construct_from_tuple, you're just not forced to
> because the code doesn't break.

Not totally sure I got my point across: I mean, if you decided to rename
construct_from_tuple as
make_from_tuple, your internal lib code can detect whether
std::make_from_tuple exists and,
in this case, replace boost:mp11::make_from_tuple definition with a
using std::make_from_tuple
declaration:

namespace boost{ namespace mp11{

#ifndef __cpp_lib_make_from_tuple
template<class T, class Tp> T make_from_tuple(Tp&& tp){...}
#else
using std::make_from_tuple;
#endif

}}

No ambiguities would then arise.

Joaquín M López Muñoz

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/bo
Edouard via Boost
2017-07-17 07:40:24 UTC
Permalink
Hi,

>This said, we can also look out to the wider world and recognize that
>Mp11 and
>Brigand have the very same design philosophy and come up with solutions that are exactly interchangeable. It would be great if we could find a way that efforts behind Mp11 and Brigand could be coordinated to come up with something bigger that could serve as Boost's pure-type metaprogramming library as >well as a non-Boost lib. To be honest, I don't have a clue how this could be done, or whether there's willingness to collaborate among Mp11's and Brigand's authors.

Brigand has been inspired by Peter Dimov's original article which explains the similarities.

There is currently redesign work going on in Brigand. Odin is considering bringing Kvasir magic into Brigand for more speed, which explains why we have been very quiet. We are very willing to collaborate, we are just busy improving the library (and our lives also :-) ).

Peter is most welcomed to take anything he likes from Brigand and incorporate it into Mp11, and I'm available by mail or on cppchat to discuss things if need be.

Kind regards.

-Edouard

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Brook Milligan via Boost
2017-07-17 00:32:33 UTC
Permalink
Before I write a review, I have a couple of questions that are the outgrowth of having been using mp11 since some time after the first two articles of Peter’s. That should suggest I generally like the library, which I do.

Nevertheless, in my code, I have found need for the following additional metafunctions:

- mp_map_keys: creates a list of keys from a map

- mp_is_map: type trait to determine whether a type is a map, i.e., has a unique set of keys

- mp_is_set: type trait to determine whether a type is a set, i.e., has unique elements

Is there a reason that support for such functions should not be in the library?

I have also found need for a metafunction that takes a map and a set of keys and returns a map with only elements with the selected keys. This is perhaps more specialized, but I can also see a general use case.

I would appreciate your thoughts on these functions.

Thanks.

Cheers,
Brook


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailm
Peter Dimov via Boost
2017-07-17 01:00:37 UTC
Permalink
Brook Milligan wrote:
> Before I write a review, I have a couple of questions that are the
> outgrowth of having been using mp11 since some time after the first two
> articles of Peter’s. That should suggest I generally like the library,
> which I do.
>
> Nevertheless, in my code, I have found need for the following additional
> metafunctions:
>
> - mp_map_keys: creates a list of keys from a map

With metaprogramming libraries, it's always quite difficult to decide what
to include and what to leave out, as there are so many useful things that
are also one-liners. As everyone has probably surmised by now, I prefer
minimalism, that is, omit by default, only include when a clear need arises.

mp_map_keys, for example, is mp_transform<mp_first, M>.

> - mp_is_set: type trait to determine whether a type is a set, i.e., has
> unique elements

This at the moment is std::is_same<S, mp_unique<S>>, although as I
mentioned, perhaps either mp_is_set or mp_distinct should indeed be
provided.

> - mp_is_map: type trait to determine whether a type is a map, i.e., has a
> unique set of keys

This is mp_is_set<mp_map_keys<M>>, although not quite if M has an element
that is not a list.

> I have also found need for a metafunction that takes a map and a set of
> keys and returns a map with only elements with the selected keys. This is
> perhaps more specialized, but I can also see a general use case.

template<class M, class L> using mp_map_subset =
mp_copy_if<M, mp_bind<mp_set_contains, L, mp_bind<mp_first,
_1>>::template fn>;

mp_copy_if_q, when I add it, will eliminate the need for the ::template fn
here.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/bo
Brook Milligan via Boost
2017-07-17 02:54:49 UTC
Permalink
> On Jul 16, 2017, at 7:00 PM, Peter Dimov via Boost <***@lists.boost.org> wrote:
>
> Brook Milligan wrote:
>> Before I write a review, I have a couple of questions that are the outgrowth of having been using mp11 since some time after the first two articles of Peter’s. That should suggest I generally like the library, which I do.
>>
>> Nevertheless, in my code, I have found need for the following additional metafunctions:
>>
>> - mp_map_keys: creates a list of keys from a map
>
> With metaprogramming libraries, it's always quite difficult to decide what to include and what to leave out, as there are so many useful things that are also one-liners. As everyone has probably surmised by now, I prefer minimalism, that is, omit by default, only include when a clear need arises.

Fair enough. The challenge is figuring out when a clear need actually does arise. I raised this set in part to see if anyone else speaks up to suggest that they are needed.

> mp_map_keys, for example, is mp_transform<mp_first, M>.

Yes, that was my implementation.

>> - mp_is_set: type trait to determine whether a type is a set, i.e., has unique elements
>
> This at the moment is std::is_same<S, mp_unique<S>>, although as I mentioned, perhaps either mp_is_set or mp_distinct should indeed be provided.

Yes, that was my implementation, too. It does feel like this is worth including as mp_distinct, but your call.

>> - mp_is_map: type trait to determine whether a type is a map, i.e., has a unique set of keys
>
> This is mp_is_set<mp_map_keys<M>>, although not quite if M has an element that is not a list.

Yes, that was also my implementation. I just punted on the question of whether or not mp_map_keys would always work. Given that it might not, this could be motivation for a more robust implementation in the library.

>> I have also found need for a metafunction that takes a map and a set of keys and returns a map with only elements with the selected keys. This is perhaps more specialized, but I can also see a general use case.
>
> template<class M, class L> using mp_map_subset =
> mp_copy_if<M, mp_bind<mp_set_contains, L, mp_bind<mp_first, _1>>::template fn>;
>
> mp_copy_if_q, when I add it, will eliminate the need for the ::template fn here.

My implementation was a bit more complicated, because I didn’t quite get how to use mp_bind correctly. Perhaps more than suggesting that this be implemented, this suggests more complete documentation on bind. At least to me, this is considerably more complex than some of the simpler metafunctions and therefore warrants more documentation, including examples.

This is likely true for many of the algorithms.

Cheers,
Brook


_______________________________________________
Unsubscribe & other changes: http://lis
Peter Dimov via Boost
2017-07-17 09:50:30 UTC
Permalink
Brook Milligan wrote:
> >> - mp_is_map: type trait to determine whether a type is a map, i.e., has
> >> a unique set of keys
> >
> > This is mp_is_set<mp_map_keys<M>>, although not quite if M has an
> > element that is not a list.
>
> Yes, that was also my implementation. I just punted on the question of
> whether or not mp_map_keys would always work. Given that it might not,
> this could be motivation for a more robust implementation in the library.

This also raises the question of what mp_is_set should do when passed
something that is not a list - return false or cause a substitution failure
(which in turn hints at the lack of mp_is_list as well).

Thank you for you suggestions. They make sense and I'll probably add them.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Peter Dimov via Boost
2017-07-17 17:16:56 UTC
Permalink
Brook Milligan wrote:

> Nevertheless, in my code, I have found need for the following additional
> metafunctions:
>
> - mp_map_keys: creates a list of keys from a map

https://github.com/pdimov/mp11/commit/50d35a29644bfb051316ae9a21f2f7b6dbe91836

> - mp_is_map: type trait to determine whether a type is a map, i.e., has a
> unique set of keys

https://github.com/pdimov/mp11/commit/34946d2ae25a1e113c23c6ead3c55224695a7bbf

> - mp_is_set: type trait to determine whether a type is a set, i.e., has
> unique elements

https://github.com/pdimov/mp11/commit/27d0d547ee4d0cb83b678b176c8e96cb78de19b5


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Fletcher, John P via Boost
2017-07-17 15:05:13 UTC
Permalink
I am interested in MP11 and will submit a review before the end of the review period.

I want to make some comments in advance of this on some topics which I have not seen discussed already. These particularly relate to mp_quote_trait which I am finding very useful to adapt old C++03 code.

In my initial work using MP11 I found that the examples given in the documentation contained some features which are not C++11 but instead C++14 or later. As I am wanting to adapt code from C++03 it is not helpful to have things which do not compile with C++11 only.

I am particularly interested in code which works out return types for functions where the application can be polymorphic. The origins of much of this code are quite old now, originating with FC++ although there are more modern versions in Boost Phoenix. See for example http://www.boost.org/doc/libs/1_64_0/libs/phoenix/doc/html/phoenix/lazy_list/background.html

One item in MP11 which I have found useful is mp_quote_trait. This seems to be a late addition to the code as it was not in the first version of the code I downloaded. One thing which was not clear to me in the documentation was how to use the resulting object. I looked for things with “q” in the name. The answer to this is mp_invoke which does not have a “q”.

Example:

using mp_q_common_type_t = mp_quote_trait<std::common_type>;
template <class... T> using result_q_t = mp_invoke<mp_q_common_type_t, T...>;

This is very helpful as the resulting code works with C++11 avoiding the need to define common_type_t which is only introduced in C++14.

I have also used the following extensions to MP11 invented to handle case where the struct to be quoted has int N at start o the list of types.

template<template<int, class...> class F> struct mp_quote_trait_N
{
template<int N, class... TN> using fn = typename F<N, TN...>::type;
};

template<class Q, int N, class... TN> using mp_invoke_N = typename Q::template fn<N,TN...>;


One application if this is the specialization the result type from a function FF with different numbers of arguments.

using mp_q_result_of_t = mp_quote_trait<boost::result_of>;
template <int N, typename FF, typename... XYZ> struct RTHelper;
template <typename FF,typename A> struct RTHelper <1,FF,A>
{
typedef mp_invoke<mp_q_result_of_t,F(A)> type;
};

and for N=2, 3 etc.

I hope this is helpful

Best wishes

John Fletcher






_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Peter Dimov via Boost
2017-07-17 15:20:10 UTC
Permalink
Fletcher, John P wrote:

> In my initial work using MP11 I found that the examples given in the
> documentation contained some features which are not C++11 but instead
> C++14 or later. As I am wanting to adapt code from C++03 it is not
> helpful to have things which do not compile with C++11 only.

I went over these at one point and tried to either remove the C++14-isms, or
mention their use and provide a C++11 alternative.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Fletcher, John P via Boost
2017-07-17 15:40:20 UTC
Permalink
________________________________________
From: Boost [boost-***@lists.boost.org] on behalf of Peter Dimov via Boost [***@lists.boost.org]
Sent: 17 July 2017 16:20
To: ***@lists.boost.org
Cc: Peter Dimov
Subject: Re: [boost] [review][mp11] Formal review of Mp11

> Fletcher, John P wrote:

> > In my initial work using MP11 I found that the examples given in the
> > documentation contained some features which are not C++11 but instead
> > C++14 or later. As I am wanting to adapt code from C++03 it is not
> > helpful to have things which do not compile with C++11 only.

> I went over these at one point and tried to either remove the C++14-isms, or
> mention their use and provide a C++11 alternative.

Thank you for that - it has made things clear to me now.

John
Fletcher, John P via Boost
2017-07-19 15:38:34 UTC
Permalink
Here is my review of MP11.

1. Should Mp11 be accepted into Boost? Please state all conditions for acceptance explicity.
Yes I think it should be accepted. There are changes I would like to see to the documentation. I don’t regard those as setting a condition on acceptance.

2. What is your evaluation of the design?
I like the design which is consistent and clear. I have found it easy to understand.

3. What is your evaluation of the implementation?
The implementation is also clear and consistent. I have found it easy to understand and to develop extensions to cover cases not in the implementation.

4. What is your evaluation of the documentation?
I have had some problems with the documentation. Some of these came up when I attempted to use the examples and found that not all of the example code was C++11 compatible. I found ways around this and I believe that this has now been sorted out.
Some items e.g. mp_identity_t<T> and mp_inherit<T…> have no documentation other that a code line and no example.
I think there is a need for more examples in some areas.

5. What is your evaluation of the potential usefulness of the library?
I think there is a great potential for this. I particularly like mp_quote_trait<F> and mp_invoke<Q,T…> which have many uses to simplify the implementation of type deduction, particularly of return types from functions. This is an area which has not been discussed much in the course of the review.

6. Did you try to use the library? With what compiler? Did you have
any problems?
I have used the library mainly with Clang 4.0 and also with gcc 4.9.2 working on Linux.

My initial problems were getting some examples to work with C++11. This is mainly the extra things which are in std for C++14. I overcame these in most cases using mp_quote_trait<F> which gave code which works with C++11 and C++14.

I have gone on to reimplement some code which does fairly complicated operations to get return types. I used mp_quote_trait<F> and mp_invoke<Q,T…> and removed all of the ::type code from my new code.
I have also written extensions to mp_quote_trait to allow for the case where the inner function is of the form F<int N,T…>.

I wanted this to allow F to be called with the contents of a list L<T…> for cases N = 1,2,3 corresponding to the number of arguments of F. For this it is necessary to call specialisations of a helper function. The code is like this, where I have defined mp_inside_N to allow access to T…

// Extensions to MP11 invented to handle case with int N at start of types.
template<template<int, class...> class F> struct mp_quote_trait_N {
template<int N, class... T> using fn = typename F<N, T...>::type;
};
template<class Q, int N, class... TN> using mp_invoke_N = typename Q::template fn<N,TN...>;
// mp_inside_N allows operations to work on the pack inside the list.
// This applies mp_invoke_N and is the case I need here.
template <class Q,class FF,class LL> struct mp_inside_N;
template <class Q,class FF, template<class...> class L, class... TL>
struct mp_inside_N <Q,FF,L<TL...> > {
typedef mp_invoke_N<Q,sizeof...(TL),FF,TL...> type;
};
using mp_q_inside_N_t = mp_quote_trait<mp_inside_N>;
// usage, where RTHelper is the helper struct e.g.
template <int N, typename FF, typename... XYZ> struct RTHelper;
template <typename FF,typename A> struct RTHelper <1,FF,A> {
typedef mp_invoke<mp_q_result_of_t,FF(A)> type;
}; // and for N=2,3 etc as needed.
using mp_q_RTHelper_t = mp_quote_trait_N<RTHelper>;
typedef mp_invoke<mp_q_inside_N_t,mp_q_RTHelper_t,FType,ArgTypes> ReturnType;

I have not used MP11 yet to write new code which I did not have before.

7. How much effort did you put into your evaluation? A glance? A quick reading? In-depth study?
I have worked for some hours for several days getting an understanding and implementing examples.

8. Are you knowledgeable about the problem domain?
I have worked for a period of years on templated code, from FC++ to Boost Phoenix. I have written some variadic codes. I am not so knowledgeable about C++14. I have explored other new libraries including Hana.

I appreciate this code and expect to go on using it. Thank you to Peter for contributing it.

John Fletcher



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Peter Dimov via Boost
2017-07-19 16:09:13 UTC
Permalink
Fletcher, John P wrote:

> Here is my review of MP11.
>
> 1. Should Mp11 be accepted into Boost? Please state all conditions for
> acceptance explicity.
> Yes I think it should be accepted. There are changes I would like to see
> to the documentation. I don’t regard those as setting a condition on
> acceptance.

Thank you John.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Brook Milligan via Boost
2017-07-19 17:47:43 UTC
Permalink
Here is my formal review of Mp11.

> On Jul 15, 2017, at 4:19 AM, Bjorn Reese via Boost <***@lists.boost.org> wrote:
>
> Mp11 is a C++11 metaprogramming library for compile-time manipulation of
> data structures that contain types. It’s based on template aliases and
> variadic templates and implements the approach outlined in the article
> "Simple C++ metaprogramming" [2] and its sequel [3]. These articles are
> useful background information for the review.

Background: at the time I first ran across these articles, I had been a reasonably proficient Boost.Mpl programmer, but was facing challenges and wanting to take advantage of c++11. I found these articles very helpful, copied a bunch of the code to explore, and learned quite a bit about metaprogramming in c++11. Thus, the foundation for Mp11 that Peter established early on was very helpful. Since then, I incorporated my copied and modified versions of the article code into a large project that needed some fairly tricky metaprogramming, and found Peter’s library very useful. Most recently, I have stripped out most of that code and made the Mp11 library an external dependency. That transition went perfectly smoothly and left only a handful of “custom” metafunctions built on top of Mp11. During the course of this review, Peter has already incorporated most of those in the library, because he agreed that they would be generally useful.

> 1. Should Mp11 be accepted into Boost? Please state all conditions
> for acceptance explicitly.

I feel Mp11 should definitely be accepted.

> 2. What is your evaluation of the design?

As mentioned above, the clarity of the design became evident to me early on after reading the original articles. At the time I was not a great c++11 programmer, but working with the early Mp11 code and extending it based upon the principles outlined in the articles was quite straightforward and taught me some useful things about c++11. I feel that the design has only improved since.

> 3. What is your evaluation of the implementation?

I have not spent much time with the current implementation. However, I did pour over the initial implementation to understand it and to extend it to cover a few additional use cases that I needed. I felt that the implementation made a lot of sense, especially in concert with the articles, which explained the “magic” really well.

> 4. What is your evaluation of the documentation?

The current documentation seems quite good, if a bit telegraphic at points. Keeping the links to the original articles is essential, and perhaps an abridged version of the most salient points would improve the introduction. It is hard to tell, because I read those articles long ago, learned their content, and have been using the library (or its precursor code) for quite awhile.

There are, however, a few points that I have found difficult and about which the documentation is probably too telegraphic. While most of the metafunctions are quite simple, i.e., take one or two arguments and return an obvious type that is easy to reason about, I have more difficulty with the metafunctions that are composable. For example, using algorithms together with bind and friends is something that I feel greater clarity, including examples, would help.

During the course of this review, I suggested a few metafunctions that I had found useful in my own code base that were simple extensions of Mp11. In all but the most complicated case, my implementation of the extension was exactly what Peter subsequently implemented in the library, having taken my suggestions to be useful enough for general consumption. I appreciate his adding to the library; more importantly, though, I feel that my ability to implement these metafunctions exactly like the pro, based only on the documentation available, is a strong indication that the document has served its purpose. At the same time, I implemented the final example (which involved an algorithm and bind) in a much more complicated way than Peter did; this too is an indication of my point above that the documentation on composing algorithms/bind/etc. into more complicated constructs can be improved.

> 5. What is your evaluation of the potential usefulness of the library?

I have been using this library (or its precursor) for the last year in a large code base. Thus, for me personally, it has already been very useful. I expect that it will be highly useful in general.

> 6. Did you try to use the library? With what compiler? Did you have
> any problems?

I have been using clang to work with the code base that uses Mp11.

> 7. How much effort did you put into your evaluation? A glance? A quick
> reading? In-depth study?

I have not put a great deal of extra effort into this specific review. However, I have been using the library for a year, during which time I have thoroughly studied the original articles, copied the code itself, and modified bits to support metafunctions that were not originally provided. This work has been spread out over months, but I feel it corresponds to an in-depth study at some level.

> 8. Are you knowledgeable about the problem domain?

I am familiar with metaprogramming in general and use it extensively in my own code base. I had earlier relied on Boost.MPL, but largely as a result of Peter’s articles and my experience with Mp11 have switched entirely to using c++11 style metaprogramming to take advantage of variadics, type aliases, etc. Thus, I feel quite comfortable with this domain.

Thanks to Peter for putting together such a carefully crafted library.

Cheers,
Brook


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listin
Zach Laine via Boost
2017-07-19 18:41:30 UTC
Permalink
On Wed, Jul 19, 2017 at 12:47 PM, Brook Milligan via Boost <
***@lists.boost.org> wrote:

> Here is my formal review of Mp11.


[snip]


>
> > 5. What is your evaluation of the potential usefulness of the library?
>
> I have been using this library (or its precursor) for the last year in a
> large code base. Thus, for me personally, it has already been very
> useful. I expect that it will be highly useful in general.
>
> > 6. Did you try to use the library? With what compiler? Did you have
> > any problems?
>
> I have been using clang to work with the code base that uses Mp11.
>
> > 7. How much effort did you put into your evaluation? A glance? A quick
> > reading? In-depth study?
>
> I have not put a great deal of extra effort into this specific review.
> However, I have been using the library for a year, during which time I have
> thoroughly studied the original articles, copied the code itself, and
> modified bits to support metafunctions that were not originally provided.
> This work has been spread out over months, but I feel it corresponds to an
> in-depth study at some level.
>

This is one of the things with which I'm struggling when considering the
use of mp11, or Brigand, or any of the other recent offerings out there.

I've found TMP so *easy* in 11 and later, that I've entirely stop using a
library to do it. I'm trying to understand why anyone would -- that's not
my making an argument, just failure of imagination. :)

Brook, could you share some example uses? Is mp11 more useful to you
because it does something that would be hard for you to get right, or
because it does lots of simple things that you'd have to repeat endlessly?
Or perhaps it's something else?

Zach

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Brook Milligan via Boost
2017-07-19 19:13:14 UTC
Permalink
> On Jul 19, 2017, at 12:41 PM, Zach Laine <***@gmail.com> wrote:
>
> I've found TMP so *easy* in 11 and later, that I've entirely stop using a library to do it. I'm trying to understand why anyone would -- that's not my making an argument, just failure of imagination. :)

It is true, that once learned type aliases, variadics, and c++11 make a _huge_ difference in one’s (at least my) ability to simplify metaprogramming. Thus, a consequence is exactly what you say, lots of individual, one-off little type aliases and such. In that sense, metaprogramming at one level is now similar to writing lambdas and such. However, see below ...

> Brook, could you share some example uses? Is mp11 more useful to you because it does something that would be hard for you to get right, or because it does lots of simple things that you'd have to repeat endlessly? Or perhaps it's something else?

Sure. One application that I have found for a more complicated library like Mp11 is the following. Consider implementing a variadic function like the following:

template < typename … Parameters >
auto f (Parameters&& … parameters)
{
return detail::f
(make_parameter_pack
(make_parameter<tag::first>().default_value(0),
make_parameter<tag::second>().default_value(1),
make_parameter<tag::third>().default_value(2)),
std::forward<Parameters>(parameters)...);
}

The idea is for detail::f() to take an object that has a variety of constraints (tags, default values, perhaps types) and an arbitrary set of arguments and glue them together into a resulting object that obeys the specified constraints. Sorting out the set of parameters and matching them against the constraints requires manipulation of lists, sets, and maps of the relevant types. I found that Mp11 made this fairly straightforward. I would not have wanted to build the infrastructure to represent and manipulate those data structures myself. I think this goes well beyond the simple type aliases that I think you are referring to above, but perhaps I misunderstand.

Another application I have found is to allow customization of a set of possible type tags that a library will support. Using lists of valid tags against which user code can be validated helps support the following: (i) customization of a library to avoid including unwanted code, and (ii) validating user code against the current configuration of the library. Again, this involves manipulating metaprogramming data structures, not simply evaluating metafunctions.

So, to me the value of something like Mp11 is that it provides some basic metaprogramming data structures, i.e., list, set, and map, along with the generic means of manipulating them. I think that is quite different from the “easy” metaprogramming you may be referring to. On the other hand, perhaps metaprogramming is much more transparent to you than to me, and you feel that managing a map in a nice generic way is “easy”.

Cheers,
Brook


_______________________________________________
Unsubscribe & other changes
Peter Dimov via Boost
2017-07-20 00:22:06 UTC
Permalink
Brook Milligan wrote:
> > 1. Should Mp11 be accepted into Boost? Please state all conditions for
> > acceptance explicitly.
>
> I feel Mp11 should definitely be accepted.

Thanks Brook.

Zach Laine wrote:
> This is one of the things with which I'm struggling when considering the
> use of mp11, or Brigand, or any of the other recent offerings out there.
>
> I've found TMP so *easy* in 11 and later, that I've entirely stop using a
> library to do it. I'm trying to understand why anyone would -- that's not
> my making an argument, just failure of imagination. :)

It gets really easy in 17 and later, as you no longer need mp_all because of
fold expressions and there are all kinds of ad-hoc primitives in the
standard library so you can get by. So for instance if you have a pack T...
you can check if all those types are const (toy example) by doing
(std::is_const_v<T> && ...), instead of mp_all<std::is_const_t<T>...> or
gathering the types into an mp_list<T...> L and then using mp_all_of<L,
std::is_const_t>.

But even then, mp_unique or mp_remove(_if) are no fun to write by hand.

In short, if what you want to do is not a simple pack expansion, you
probably want to use the library. That, or reimplement it. :-)


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
peterkochlarsen via Boost
2017-07-22 18:30:50 UTC
Permalink
Boost - Dev mailing list wrote
> The formal review of Peter Dimov's Mp11 library is scheduled for
> July 15 - July 24, 2017 [1].
>
> 1. Should Mp11 be accepted into Boost? Please state all conditions
> for acceptance explicity.

Yes. Especially so if mp11 can be merged with the ideas from kvasir and
brigand.

> 2. What is your evaluation of the design?

I like the design, it is elegant and easy to understand.

> 3. What is your evaluation of the implementation?

It is solid. I would like to see some improvement in the sort algorithm,
however.

> 4. What is your evaluation of the documentation?

The documentation is well-written. Easy to read, making it easy to find the
stuff you need.

> 5. What is your evaluation of the potential usefulness of the library?

It would be very useful to me. I currently use the brigand library and find
that library also very good. But if mp11 is acepted into boost, I will
switch.

> 6. Did you try to use the library? With what compiler? Did you have
> any problems?

No, due to time pressure, I did not have time to use the library.

> 7. How much effort did you put into your evaluation? A glance? A quick
> reading? In-depth study?

A quick reading this time. I have been following Peter Dimovs work for some
years though, beginning with his introduction to template metaprogramming
which was an eye-opener to me.

> 8. Are you knowledgeable about the problem domain?

I am somewhat knowledgeable as I have implemented a template-library (much
more limited in scope) and thus have lots of knowledge about how not to do
template meta programming. ;-)
I am also a user of brigand, and use it a lot - as my current project is
(ab)using templates all over the place.

/Peter




--
View this message in context: http://boost.2283326.n4.nabble.com/review-mp11-Formal-review-of-Mp11-tp4696839p4697275.html
Sent from the Boost - Dev mailing list archive at Nabble.com.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Peter Dimov via Boost
2017-07-22 19:10:54 UTC
Permalink
peterkochlarsen wriote:
> > 1. Should Mp11 be accepted into Boost? Please state all conditions
> > for acceptance explicity.
>
> Yes. Especially so if mp11 can be merged with the ideas from kvasir and
> brigand.

Thanks.

> > 3. What is your evaluation of the implementation?
>
> It is solid. I would like to see some improvement in the sort algorithm,
> however.

What specifically? It holds its own pretty well on metaben.ch, on Clang 4 it
loses only to kvasir (but then again, who doesn't lose to kvasir?)


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Peter Koch Larsen via Boost
2017-07-23 06:02:35 UTC
Permalink
On Sat, Jul 22, 2017 at 9:10 PM, Peter Dimov via Boost
<***@lists.boost.org> wrote:
> peterkochlarsen wriote:
>>
>> > 1. Should Mp11 be accepted into Boost? Please state all conditions >
>> > for acceptance explicity.
>>
>> Yes. Especially so if mp11 can be merged with the ideas from kvasir and
>> brigand.
>
>
> Thanks.
>
>> > 3. What is your evaluation of the implementation?
>>
>> It is solid. I would like to see some improvement in the sort algorithm,
>> however.
>
>
> What specifically? It holds its own pretty well on metaben.ch, on Clang 4 it
> loses only to kvasir (but then again, who doesn't lose to kvasir?)

Sorry about the noise. As part of my review I went through the
benchmarks at metaben.ch. I saw that sort performed badly for mp11,
but revisiting the site I realise that I misread the graph.

/Peter

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
vijayan via Boost
2017-07-23 14:20:46 UTC
Permalink
> 1. Should Mp11 be accepted into Boost?

Yes.


> 2. What is your evaluation of the design?

It appears to be robust. I'm not sure about the design decision mp_ prefix
for everything.


> What is your evaluation of the implementation?

I haven't looked at it in detail.


> 4. What is your evaluation of the documentation?

Good. Very good.


> 5. What is your evaluation of the potential usefulness of the library?

Quite high; should replace a lot of current boost MPL usage.


> 6. Did you try to use the library? With what compiler? Did you have any
problems?

Only cursorily. With g++ 7.1 and clang++ 4.0.
Did not encounter any problems.


> 8. Are you knowledgeable about the problem domain?

Somewhat. To the extent that I've used boost MPL quite a lot.





On 15 July 2017 at 15:49, Bjorn Reese via Boost-announce <
boost-***@lists.boost.org> wrote:

> The formal review of Peter Dimov's Mp11 library is scheduled for
> July 15 - July 24, 2017 [1].
>
> Mp11 is a C++11 metaprogramming library for compile-time manipulation of
> data structures that contain types. It’s based on template aliases and
> variadic templates and implements the approach outlined in the article
> "Simple C++ metaprogramming" [2] and its sequel [3]. These articles are
> useful background information for the review.
>
> * Mp11 aims to make simple usage simple, and to support complex usage
> without complicating the simple use cases.
>
> * Mp11 works on any type-list, whether its own type-list mp_list,
> or standard type-lists such as std::tuple and std::variant, or
> user-defined type-lists.
>
> * Mp11 works with any meta-function, such as C++11 or Boost
> type-traits, or user-defined type-traits.
>
> Mp11 can be found here:
>
> * Documentation: https://rawgit.com/pdimov/mp11
> /master/doc/html/mp11.html
>
> * Source code: https://github.com/pdimov/mp11/tree/master
>
>
> Please answer the following questions in your review [4]:
>
> 1. Should Mp11 be accepted into Boost? Please state all conditions
> for acceptance explicity.
>
> 2. What is your evaluation of the design?
>
> 3. What is your evaluation of the implementation?
>
> 4. What is your evaluation of the documentation?
>
> 5. What is your evaluation of the potential usefulness of the library?
>
> 6. Did you try to use the library? With what compiler? Did you have
> any problems?
>
> 7. How much effort did you put into your evaluation? A glance? A quick
> reading? In-depth study?
>
> 8. Are you knowledgeable about the problem domain?
>
>
> [1] http://www.boost.org/community/review_schedule.html
> [2] http://pdimov.com/cpp2/simple_cxx11_metaprogramming.html
> [3] http://pdimov.com/cpp2/simple_cxx11_metaprogramming_2.html
> [4] http://www.boost.org/community/reviews.html
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman
> /listinfo.cgi/boost-announce

_______________________________________________
Unsubscribe & other changes: h
Robert Ramey via Boost
2017-07-23 17:34:00 UTC
Permalink
On 7/15/17 3:19 AM, Bjorn Reese via Boost wrote:

Here is my review.

> Please answer the following questions in your review [4]:
>
> 1. Should Mp11 be accepted into Boost? Please state all conditions
> for acceptance explicity.
YES
>
> 2. What is your evaluation of the design?
Incredible
>
> 3. What is your evaluation of the implementation?
fantastic
>
> 4. What is your evaluation of the documentation?
excellent - but see notes below
>
> 5. What is your evaluation of the potential usefulness of the library?
beyond believe
>
> 6. Did you try to use the library? With what compiler? Did you have
> any problems?
no. Actually I was unclear whether I need C++11 or C++14
>
> 7. How much effort did you put into your evaluation? A glance? A quick
> reading? In-depth study?
Not much - Spend maybe 2 hours trying to figure out the documentation.
Not enough time - but I feel I have a fairly good understanding of
>
> 8. Are you knowledgeable about the problem domain?
More than average, but not as much as some


Observations:

Much has been said about the mp_ prefix. I'm not crazy about it as I
would much prefer to use mp11::transform rather than mp11::mp_transform.
But I'm not really bothered by it all that much. It seems that Peter
has made a case for it and it's being discussed. I don't much about
this so I'm happy with whatever is finally used.

Calling this a library does not do it justice. It's nothing less than
the text book of how C++11+ should/can be used. I would like to see
even more examples and expository examples. It should really be a book
- sequel to Abrahams and Gurtovoy's book which itself was sequel to
Alexandrescu's book.

I started reading the documents and kept these notes. I quit when I ran
out of gas.

==============

Incorporation of Simple C++ meta programming and sequel int to the
documentation directly rather than by reference. I'm guessing this
might be part of a section - "how the library is implemented".

I would also like to see a section which describes the parallels with
boost mpl. I see this is a newer, better, simpler, faster, more modern,
etc. replacement for mpl. Assuming I'm correct I would like to see this
described in a separate section titled something like -
background/history or something similar.

Definitions

A "quoted metafunction" is a class with a public metafunction member
called fn, ...

I presume that this is the same as the mpl notion of metafunction class
which must contain a public metafunction member called "apply"

A "map" is a list of lists, the inner lists having at least one element
(the key.) The keys of the map must be unique.

From the examples, I can't discern what the key is. Is it the first
element of each set? or ...

Generating test cases

This is a great motivating example. For the safe numerics library I
used the Boost.Preprocessor library for this purpose. Had this existed
at the time, I would have turned to it first. It's a use case which is
useful in the real world.

It's unclear whether one needs C++11 or C++14 in order to use this library.

Writing common_type Specializations

This example is more complicated and I'm having a hard time
understanding it. This is not a criticism - I just think I have invest
more effort. I'm motivated as I believe it has some relevence to some
stuff I'm currently working on.

But I'm having trouble with the example:

I seems that mp_defer is related if not equivalent to the mpl notion of
"eval_if". I'm not clear on this since mp_defer isn't really describe

The example also reference mp_transform whose purpose is not obvious.

One thing that might be making it difficult for me is the usage of
common_type_t for the example metafunction name which uses
std::common_type in it's implementation. Then there is common_tuple.
Perhaps altering the names might make all this more understandable to
the normal brain.

Soooo - consider:

a) thinking some more about the names
b) inserting comments into the example code
c) perhaps reformation the code somewhat keep the comments in a good place
d) including information - a cheat sheet which relates notions in this
library to notions/nomenclature in boost.mpl. Or consider using the MPL
nomenclature. This latter idea is intersting as this is clearly meant
to be the "modern" version of MPL.
e) thie common_type_t is just an alias for std::common_type. I'm not
convinced it clarifies anything.

With all that the example might look more like:

"Let’s write a common_type specialization for two std::tuple arguments
which we'll call common_tuple."

Hmmm - what is this going to return? It sounds like that it's going to
produce a new tuple where the first element is the common_type of first
element of each constituent tuple, the second is the common_type of
second tuple and so forth. But that's just a guess though

create a tuple from

template<class Tp1, class Tp2> using common_tuple =
// mp_transform does ... what - returns a tuple (li
mp_transform<
std::common_type, // from standard C++14
Tp1, // first tuple ?
Tp2 // second tuple ?
>;

Then specialize std::common_type to use the above ...

OK have written the above it might be making sense to me now. My basic
point is that these examples need a lot of extra care as they are
essential to explaining what the library is for an how to use it to most
programmers. I've worked many years with MPL and still I have
difficulty understanding all this.

Looking back I see that mp_transform IS described in the overview. I
didn't pay much attention to the overview as reading something labeled
"overview" is for wimps. Now that I look back on it I see that I should
have read it. The first sentence exactly and succinctly describes what
the library does. I think this sentence should have it's own paragraph.

This library is not really a library. Its an unlibrary.

"As another example, consider the hypothetical type expected<T, E…​>"

Another excellent example. Although its related to the previous one, it
should have it's own heading. It's particularly interesting given all
the thunder and lightening that this topic has recently received.

"Fixing tuple cat"

This example would require many hours and referring to another paper to
figure out. I don't think it's suitable as an introduction to the library.

"Computing Return types"

Another good example. From the first paragraph I understood the problem
and the proposed solution using variant. Given that I'm already getting
burned out from reading this stuff, I decided to declare victory and
move on.

"Reference"

I absolutely loved having the table of contents in the left hand window
of the documentation. I fund it very, very, very helpful and intuitive.
I do question the fact that reference section includes just a couple
of lines for each library function. I much prefer and learned a lot
from the boost mpl documentation which includes a small compilable
example for each function. Maybe you might lift those examples and
include them here. A lot of work I know, but that's why you get paid
the big bucks. Actually I would prefer for web documentation that each
metafunction have it's own page, with type requirements for the
parameters, and small self contained examples.

This is not really a library, it's an exposition how to use of C++11++.
It's a way of training the next generation of programmers to use TMP.
They will be standing on your shoulders by means of this document. I
think you way underestimate this document and library will have on the
future.

===========

Robert Ramey


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/bo
Glen Fernandes via Boost
2017-07-23 17:44:04 UTC
Permalink
What follows is my review of the Mp11 library:

[Should the library be accepted into Boost?]

Yes. I vote for an unconditional ACCEPT.

[What is your evaluation of the design?]

Excellent. The design where any template can serve as a list, and any template
can serve as a meta-function is both elegant and powerful. The additional
quoted meta-function support with utilities such as mp_bind, mp_bind_front,
and mp_bind_back, addresses the other request I had when reviewing an earlier
version of Mp11. While HOMF were never essential, as the article pointed out,
users appreciate more ways to one-line things without having to write a helper
type. Some additional primitives are desired, as mentioned later in this
review (e.g. min and max functionality) but overall the toolkit is already
vast and useful.

[What is your evaluation of the implementation?

Excellent. The focus on performance is definitely appreciated while we still
have to depend on libraries for many of these meta-programming primitives.
Ideally many of these would be provided in the standard library and have
implementations that only a compiler vendor could provide with built in
support, and offer performance beyond what a library could offer. In the
meanwhile, the performance offered by Mp11 is great, more than sufficient for
my needs, and in my opinion also for the majority of users. In comparison, the
tiny C++11 meta-programming library that I have implemented, uses only the
obvious C++11 implementations for most functionality, and does not offer the
same fast compile times as the equivalents in Mp11. The techniques used by
Mp11 via C++11 constexpr, C++14 constexpr, and even C++17 fold expressions,
besides improving Mp11 performance, were a valuable source to learn from.

Suggestion: Can all the workarounds for MSVC versions 1800 and older for the
empty list cases be avoided by instead using a helper trait? i.e.

template<template<class...> class L, class... T, template<class...> class P>
struct mp_find_if_impl<L<T...>, P> {
using type = typename mp_find_if_impl_2<P, T...>::type;
};

i.e. Introduce mp_find_if_impl_2 which would then have the obvious
implementation as before, only without requiring the MSVC workaround? This is
only worth considering if you find it to offer some benefit such as:
Additional maintainability of the Mp11 code, with less workarounds, and no
costs, e.g. no increase in compilation times as a consequence.

[What is your evaluation of the documentation?

Very good. The reference documentation is clear, and easily understood. More
example and tutorial content before the reference section would always be
welcome, but not necessary.

Suggestion: The two-part article that Peter wrote (which is referenced in
the documentation) is in my opinion so valuable for users to gain better
understanding and appreciation of the library that it should be included in
the library distribution as part of the documentation. Ideally in the same
Asciidoc form as the current documentation, as a supplemental document (or
Appendix entry).

Suggestion: Does it make sense for the documentation to have a section
describing the conventions the library uses, for potential contributors as
much as users? e.g. If someone was designing an mp_min_element, should it
yield the element type result, or the list index size constant result? Is
there an established convention of when an error is acceptable for an empty
list versus returning an index?

Correction: Under heading mp_find_if<L, P>: "mp_find_f<L, P> is an" should be
"mp_find_if<L, P> is an".

[What is your evaluation of the potential usefulness of the library?

Incredibly useful in its current form, and this is only going to increase as
the library is extended based on user requests for additional functionality.
Almost every meta-programming primitive that I have needed recently either
already exists in Mp11, or I am able to implement using Mp11 with a little
effort. During this review I replaced the use of my own meta-programming
library in a project of mine without any issues. As part of this review I also
tried several exercises where I implemented certain traits and meta-functions
using Mp11. Of all the exercises that I attempted, the only one where the
library lacked the necessary utility was an "mp_min_element" function:

This was an implementation of the typical "type_with_alignment" trait, which
can easily be implemented using a "min_element" functionality. Mp11 does not
have mp_min, mp_max, mp_min_element, mp_max_element presently, and I believe
they should be added because they are useful and users will probably find
themselves implementing it. Sure, mp_sort exists, but I would not use a sort
when a min_element can suffice. In this case, type_with_alignment<N> could use
mp_min_element with a predicate that finds the type in an mp_list of several
scalar types, that matches has an alignment of at least N and has the smallest
size, and then check that the result element type of the mp_min_element is at
least N.

The litmus test for me for a meta-programming library is the question: Would I
use Mp11 in library code? The answer for me is "yes". If it was part of Boost,
I would use it in other Boost libraries (that already require C++11 or
higher).

[Did you try to use the library? With which compiler(s)?
Did you have any problems?]

Yes. I used the library as a replacement for an existing meta-programming
library of mine in real (non-toy, non-exercise) project code that is compiled
with g++ 4.8.5 in c++11 mode for x86 and x86_64 Linux, using Boost 1.64.0, on
64-bit RHEL 6 and measured compilation times. I also used the library in a few
exercises that I compiled with g++ 7.1 and clang 4.0.0, for x86 and x86_64
Linux, using the current Boost master branch, for c++11 and c++14, on 64-bit
Fedora 26, and again measured compilation times. I also compiled and ran the
Mp11 unit tests with the compilers, C++ standard modes, architectures, Boost
distributions, and operating systems mentioned.

[How much effort did you put into your evaluation? A glance? A quick reading?
In-depth study?]

More than ten hours over this weekend reading the documentation, reviewing the
implementation and tests, using Mp11 in a project replacing my own C++11
meta-programming library, using it in various exercises, and running the Mp11
unit tests with the various compilers, C++ standard modes, targets, and Boost
distributions listed above. Prior to the preparation for the review, I had
spent some time with an earlier version of Mp11 and comparing it to Metal for
implementing a few meta-functions, including the "instantiates_" example from
my library:

instantiates_<T, templates_<std::set, std::multiset, std::unordered_set> >

Where instantiates_ should be implemented in terms of "is_instantiation_of_":

is_instantiation_of_<T, std::set>

Which has the obvious behavior indicated by the trait name. The Mp11 approach
provided by Peter for this case, and the relative ease with which I was able
to implement the other meta-functions using Mp11 were a convincing
demonstration of the usefulness of the library.

[Are you knowledgeable about the problem domain?]

Like many of us, I had written a meta-programming library as C++11 language
features have become available. Before that, if Boost.MPL solved a problem,
more often than not it was convenient and useful enough to just use it, even
if writing my own implementation would result in faster compilation times.
Peter's article, however, opened my eyes to a more elegant design, and changed
how I implemented my C++11 meta-programming library, and in general shaped
what I think about meta-programming in modern C++.

Thank you Peter for your work on Mp11, for submitting it for inclusion in
Boost, and for the articles that motivated it and taught the rest of us.

Glen

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Peter Koch Larsen via Boost
2017-07-23 18:08:16 UTC
Permalink
I would like to add my opinion about the mp_ prefix. Many do not like
it, but I actually believe it is very nice to have a name that stands
out.
Apart for reducing the likelihood that there will be a name-clash if
the library should get accepted into the standard, there is also the
advantage that you can easily see that this is a mp_ function. Other
libraries have adopted a standard of simply appending an underscore
after the name so that the library char becomes char_.
If your eyesight is not perfect, this convention becomes a pain. I
have myself spent hours trying to decrypt weird error-messages (most
notably in spirit) to realise that an underscore was missing.
So hooray for mp_. ;-)

/Peter

On Sun, Jul 23, 2017 at 7:44 PM, Glen Fernandes via Boost
<***@lists.boost.org> wrote:
> What follows is my review of the Mp11 library:
>
> [Should the library be accepted into Boost?]
>
> Yes. I vote for an unconditional ACCEPT.
>
> [What is your evaluation of the design?]
>
> Excellent. The design where any template can serve as a list, and any template
> can serve as a meta-function is both elegant and powerful. The additional
> quoted meta-function support with utilities such as mp_bind, mp_bind_front,
> and mp_bind_back, addresses the other request I had when reviewing an earlier
> version of Mp11. While HOMF were never essential, as the article pointed out,
> users appreciate more ways to one-line things without having to write a helper
> type. Some additional primitives are desired, as mentioned later in this
> review (e.g. min and max functionality) but overall the toolkit is already
> vast and useful.
>
> [What is your evaluation of the implementation?
>
> Excellent. The focus on performance is definitely appreciated while we still
> have to depend on libraries for many of these meta-programming primitives.
> Ideally many of these would be provided in the standard library and have
> implementations that only a compiler vendor could provide with built in
> support, and offer performance beyond what a library could offer. In the
> meanwhile, the performance offered by Mp11 is great, more than sufficient for
> my needs, and in my opinion also for the majority of users. In comparison, the
> tiny C++11 meta-programming library that I have implemented, uses only the
> obvious C++11 implementations for most functionality, and does not offer the
> same fast compile times as the equivalents in Mp11. The techniques used by
> Mp11 via C++11 constexpr, C++14 constexpr, and even C++17 fold expressions,
> besides improving Mp11 performance, were a valuable source to learn from.
>
> Suggestion: Can all the workarounds for MSVC versions 1800 and older for the
> empty list cases be avoided by instead using a helper trait? i.e.
>
> template<template<class...> class L, class... T, template<class...> class P>
> struct mp_find_if_impl<L<T...>, P> {
> using type = typename mp_find_if_impl_2<P, T...>::type;
> };
>
> i.e. Introduce mp_find_if_impl_2 which would then have the obvious
> implementation as before, only without requiring the MSVC workaround? This is
> only worth considering if you find it to offer some benefit such as:
> Additional maintainability of the Mp11 code, with less workarounds, and no
> costs, e.g. no increase in compilation times as a consequence.
>
> [What is your evaluation of the documentation?
>
> Very good. The reference documentation is clear, and easily understood. More
> example and tutorial content before the reference section would always be
> welcome, but not necessary.
>
> Suggestion: The two-part article that Peter wrote (which is referenced in
> the documentation) is in my opinion so valuable for users to gain better
> understanding and appreciation of the library that it should be included in
> the library distribution as part of the documentation. Ideally in the same
> Asciidoc form as the current documentation, as a supplemental document (or
> Appendix entry).
>
> Suggestion: Does it make sense for the documentation to have a section
> describing the conventions the library uses, for potential contributors as
> much as users? e.g. If someone was designing an mp_min_element, should it
> yield the element type result, or the list index size constant result? Is
> there an established convention of when an error is acceptable for an empty
> list versus returning an index?
>
> Correction: Under heading mp_find_if<L, P>: "mp_find_f<L, P> is an" should be
> "mp_find_if<L, P> is an".
>
> [What is your evaluation of the potential usefulness of the library?
>
> Incredibly useful in its current form, and this is only going to increase as
> the library is extended based on user requests for additional functionality.
> Almost every meta-programming primitive that I have needed recently either
> already exists in Mp11, or I am able to implement using Mp11 with a little
> effort. During this review I replaced the use of my own meta-programming
> library in a project of mine without any issues. As part of this review I also
> tried several exercises where I implemented certain traits and meta-functions
> using Mp11. Of all the exercises that I attempted, the only one where the
> library lacked the necessary utility was an "mp_min_element" function:
>
> This was an implementation of the typical "type_with_alignment" trait, which
> can easily be implemented using a "min_element" functionality. Mp11 does not
> have mp_min, mp_max, mp_min_element, mp_max_element presently, and I believe
> they should be added because they are useful and users will probably find
> themselves implementing it. Sure, mp_sort exists, but I would not use a sort
> when a min_element can suffice. In this case, type_with_alignment<N> could use
> mp_min_element with a predicate that finds the type in an mp_list of several
> scalar types, that matches has an alignment of at least N and has the smallest
> size, and then check that the result element type of the mp_min_element is at
> least N.
>
> The litmus test for me for a meta-programming library is the question: Would I
> use Mp11 in library code? The answer for me is "yes". If it was part of Boost,
> I would use it in other Boost libraries (that already require C++11 or
> higher).
>
> [Did you try to use the library? With which compiler(s)?
> Did you have any problems?]
>
> Yes. I used the library as a replacement for an existing meta-programming
> library of mine in real (non-toy, non-exercise) project code that is compiled
> with g++ 4.8.5 in c++11 mode for x86 and x86_64 Linux, using Boost 1.64.0, on
> 64-bit RHEL 6 and measured compilation times. I also used the library in a few
> exercises that I compiled with g++ 7.1 and clang 4.0.0, for x86 and x86_64
> Linux, using the current Boost master branch, for c++11 and c++14, on 64-bit
> Fedora 26, and again measured compilation times. I also compiled and ran the
> Mp11 unit tests with the compilers, C++ standard modes, architectures, Boost
> distributions, and operating systems mentioned.
>
> [How much effort did you put into your evaluation? A glance? A quick reading?
> In-depth study?]
>
> More than ten hours over this weekend reading the documentation, reviewing the
> implementation and tests, using Mp11 in a project replacing my own C++11
> meta-programming library, using it in various exercises, and running the Mp11
> unit tests with the various compilers, C++ standard modes, targets, and Boost
> distributions listed above. Prior to the preparation for the review, I had
> spent some time with an earlier version of Mp11 and comparing it to Metal for
> implementing a few meta-functions, including the "instantiates_" example from
> my library:
>
> instantiates_<T, templates_<std::set, std::multiset, std::unordered_set> >
>
> Where instantiates_ should be implemented in terms of "is_instantiation_of_":
>
> is_instantiation_of_<T, std::set>
>
> Which has the obvious behavior indicated by the trait name. The Mp11 approach
> provided by Peter for this case, and the relative ease with which I was able
> to implement the other meta-functions using Mp11 were a convincing
> demonstration of the usefulness of the library.
>
> [Are you knowledgeable about the problem domain?]
>
> Like many of us, I had written a meta-programming library as C++11 language
> features have become available. Before that, if Boost.MPL solved a problem,
> more often than not it was convenient and useful enough to just use it, even
> if writing my own implementation would result in faster compilation times.
> Peter's article, however, opened my eyes to a more elegant design, and changed
> how I implemented my C++11 meta-programming library, and in general shaped
> what I think about meta-programming in modern C++.
>
> Thank you Peter for your work on Mp11, for submitting it for inclusion in
> Boost, and for the articles that motivated it and taught the rest of us.
>
> Glen
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Vinnie Falco via Boost
2017-07-23 18:15:59 UTC
Permalink
On Sun, Jul 23, 2017 at 11:08 AM, Peter Koch Larsen via Boost
<***@lists.boost.org> wrote:
> I would like to add my opinion about the mp_ prefix. Many do not like
> it, but I actually believe it is very nice to have a name that stands
> out.

I like it too but let me propose an alternative sure to displease everyone:

In addition to mp11::mp_*, the library can provide a set of alternate
aliases in the namespace mp11::alternatives::. For example
mp11::alternatives::transform, or mp11::alternatives::if_

People who feel strongly about names similar to MPL or who despise the
mp_ prefix can simply lift this alternate set of names into the
namespace of their choosing. For example:

namespace mp = mp11::alternatives;

Lets you use mp::transform, mp::if_

Thanks

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Edward Diener via Boost
2017-07-23 19:55:43 UTC
Permalink
On 7/23/2017 2:15 PM, Vinnie Falco via Boost wrote:
> On Sun, Jul 23, 2017 at 11:08 AM, Peter Koch Larsen via Boost
> <***@lists.boost.org> wrote:
>> I would like to add my opinion about the mp_ prefix. Many do not like
>> it, but I actually believe it is very nice to have a name that stands
>> out.
>
> I like it too but let me propose an alternative sure to displease everyone:

It displeases me and I usually like options. I think such a complication
is unnecessary.

>
> In addition to mp11::mp_*, the library can provide a set of alternate
> aliases in the namespace mp11::alternatives::. For example
> mp11::alternatives::transform, or mp11::alternatives::if_
>
> People who feel strongly about names similar to MPL or who despise the
> mp_ prefix can simply lift this alternate set of names into the
> namespace of their choosing. For example:
>
> namespace mp = mp11::alternatives;
>
> Lets you use mp::transform, mp::if_
>
> Thanks


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Steven Watanabe via Boost
2017-07-23 20:31:33 UTC
Permalink
AMDG

On 07/23/2017 12:15 PM, Vinnie Falco via Boost wrote:
> On Sun, Jul 23, 2017 at 11:08 AM, Peter Koch Larsen via Boost
> <***@lists.boost.org> wrote:
>> I would like to add my opinion about the mp_ prefix. Many do not like
>> it, but I actually believe it is very nice to have a name that stands
>> out.
>
> I like it too but let me propose an alternative sure to displease everyone:
>
> In addition to mp11::mp_*, the library can provide a set of alternate
> aliases in the namespace mp11::alternatives::. For example
> mp11::alternatives::transform, or mp11::alternatives::if_
>

I'm not fond of the mp_ prefix, but providing
multiple names for the same thing for no
good reason other than some people's personal
preferences is worse.

> People who feel strongly about names similar to MPL or who despise the
> mp_ prefix can simply lift this alternate set of names into the
> namespace of their choosing. For example:
>
> namespace mp = mp11::alternatives;
>
> Lets you use mp::transform, mp::if_
>

In Christ,
Steven Watanabe


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Gavin Lambert via Boost
2017-07-25 03:16:39 UTC
Permalink
On 24/07/2017 06:15, Vinnie Falco wrote:
> I like it too but let me propose an alternative sure to displease everyone:
>
> In addition to mp11::mp_*, the library can provide a set of alternate
> aliases in the namespace mp11::alternatives::. For example
> mp11::alternatives::transform, or mp11::alternatives::if_
>
> People who feel strongly about names similar to MPL or who despise the
> mp_ prefix can simply lift this alternate set of names into the
> namespace of their choosing. For example:
>
> namespace mp = mp11::alternatives;
>
> Lets you use mp::transform, mp::if_

Rather than try to guess at someone's preferences for alternate naming,
you can just let them write their own header file that imports using
whatever naming they like.

(This used to be a bit of a pain in the butt for templates pre-C++11,
but now it's a snap.)


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Roberto Hinz via Boost
2017-07-24 01:36:06 UTC
Permalink
Hi,

my review ( this is my first one ):

1. Should Mp11 be accepted into Boost? Please state all conditions
for acceptance explicitly.

Yes. No conditions.


2. What is your evaluation of the design?

I don't know the other MP libraries, so I lack some basis of comparison
But anyway, the library is easy to use an has vast application.
So I find the design very good.

I have nothing against the mp_ prefix,

There are just some names I would change.
Nothing really important. Just matter of personal taste.
But will mention them to see if others agree:

mp_eval_if_c<C, T, F, U…​>
From this name I would expect F<U...> to be evaluated
when C is true, instead of when it's false.

mp_take
The name doesn't make it clear what it is taking.
I would rather call it mp_front_slice, or
something like that.


3. What is your evaluation of the implementation?

Very good: has good performance, well organized,
easy to understand and to maintain.


4. What is your evaluation of the documentation?

I found the reference easy to follow.

The examples required some effort. But only because
they really exercise my understanding.
And that's a good thing, IMO.

TMP requires from the newcomers to think in a
different way and the two preliminary articles are
really helpful in this sense. I found them very valuable.
They made me fell stimulated instead of intimidated.


5. What is your evaluation of the potential usefulness of the library?

Some claimed that modern C++ makes TMP so much easier
that TMP libraries brings little benefit today.

But sometimes is not that easy to figure out which
solution to a certain problem would perform better,
specially when one is not very experienced.
The author benchmarked different solutions
to pick the best. This makes the library valuable.

Some of the tools provided by the library are trivial
to implement but very general purpose. So it's nice to
have them in a library so that one doesn't need to
reimplement one's own version repeatedly.

Hence I find the library useful.


6. Did you try to use the library? With what compiler? Did you have
any problems?

Did not use it.


7. How much effort did you put into your evaluation? A glance? A quick
reading? In-depth study?

Most of the time I spent studying the articles and the examples.
I took a glance in the code.


8. Are you knowledgeable about the problem domain?

Not much. I started doing some more heavy TMP only more recently.
As I said, I don't know the other TMP libraries


Roberto

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listi
Loading...