[review][mp11] Formal review of Mp11
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
On Sat, Jul 15, 2017 at 3:19 AM, Bjorn Reese via Boost
* 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?
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.
On Sat, Jul 15, 2017 at 3:19 AM, Bjorn Reese via Boost
The formal review of Peter Dimov's Mp11 library is scheduled for July 15 - July 24, 2017 [1].
* The documentation states: "mp_if_c
Vinnie Falco wrote:
* The documentation states: "mp_if_c
is an alias for T. mp_if_c is an alias for E. Otherwise, the result is a substitution failure." Should that read "mp_if_c
"? If not, why?
No.
The idea here is that mp_if_c can be used in two ways. One is mp_if_c
On 07/15/17 15:47, Peter Dimov via Boost wrote:
Vinnie Falco wrote:
* The documentation states: "mp_if_c
is an alias for T. mp_if_c is an alias for E. Otherwise, the result is a substitution failure." Should that read "mp_if_c
"? If not, why? No.
The idea here is that mp_if_c can be used in two ways. One is mp_if_c
, which gives either T or E depending on Cond. The other is mp_if_c , which is the same as std::enable_if_t - gives T when Cond, otherwise a substitution failure. So
mp_if_c
is T mp_if_c is T mp_if_c 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
is T mp_if_c 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.
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
On 07/15/17 15:47, Peter Dimov via Boost wrote:
Vinnie Falco wrote:
* The documentation states: "mp_if_c
is an alias for T. mp_if_c is an alias for E. Otherwise, the result is a substitution failure." Should that read "mp_if_c
"? If not, why? No.
The idea here is that mp_if_c can be used in two ways. One is mp_if_c
, which gives either T or E depending on Cond. The other is mp_if_c , which is the same as std::enable_if_t - gives T when Cond, otherwise a substitution failure. So
mp_if_c
is T mp_if_c is T mp_if_c 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
is T mp_if_c 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
On Sat, Jul 15, 2017 at 5:57 AM, Andrey Semashev via Boost
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
Andrey Semashev wrote:
The idea here is that mp_if_c can be used in two ways. One is mp_if_c
, which gives either T or E depending on Cond. The other is mp_if_c , which is the same as std::enable_if_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
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...
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...
https://github.com/pdimov/mp11/blob/8e1d23b11f25c3864593b6fc5a8449306e17ea23...
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/e507494b5f7f51026e8afa317b3ca2c058a4d2...
and here's mp11
https://github.com/pdimov/mp11/blob/8e1d23b11f25c3864593b6fc5a8449306e17ea23...
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
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:
and here's mp11
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-tp46968... Sent from the Boost - Dev mailing list archive at Nabble.com.
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/91f2b32cf5a27b3aeaaf...
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<
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
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!
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
> -> 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
{};
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
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.
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
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
, 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
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
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?
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
Joaquin M López Muñoz wrote:
Something more generic can be provided
struct mp_mpl_sequence_folder { template
struct apply{using type=mp_push_front ;}; }; 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
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 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 class L,typename... Ts,typename T>
static L
On Tue, Jul 18, 2017 at 9:58 AM, Joaquin M López Muñoz via Boost < 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 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/85d6d32f6e58e648c4573189f8bf2d763... [2]: https://github.com/brunocodutra/metal/blob/85d6d32f6e58e648c4573189f8bf2d763... Bruno
Bruno Dutra wrote:
How about we provide it in MPL instead?
namespace mpl {
template
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.
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
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
, 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
On Mon, Jul 17, 2017 at 1:06 AM, Peter Dimov via Boost < 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
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
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 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,G,mp_list
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,G,mp_list
>
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.
https://github.com/joaquintides/multi_index_mp11/commit/91f2b32cf5a27b3aeaaf...
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
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.
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
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
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
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
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_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, 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
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
On Jul 16, 2017, at 7:00 PM, Peter Dimov via Boost
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
.
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
, 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
, 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
using mp_map_subset = mp_copy_if >::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
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
, 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.
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/50d35a29644bfb051316ae9a21f2f7b6dbe918...
- 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/34946d2ae25a1e113c23c6ead3c55224695a7b...
- mp_is_set: type trait to determine whether a type is a set, i.e., has unique elements
https://github.com/pdimov/mp11/commit/27d0d547ee4d0cb83b678b176c8e96cb78de19...
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...
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_traitstd::common_type;
template
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.
________________________________________ From: Boost [boost-bounces@lists.boost.org] on behalf of Peter Dimov via Boost [boost@lists.boost.org] Sent: 17 July 2017 16:20 To: boost@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 _______________________________________________ Unsubscribe & other changes: https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Flists.boost.org%2Fmailman%2Flistinfo.cgi%2Fboost&data=02%7C01%7CJ.P.Fletcher%40aston.ac.uk%7C350ec137efc54797930c08d4cd275bdd%7Ca085950c4c2544d5945ab852fa44a221%7C0%7C0%7C636359016309074831&sdata=tfC%2BwHzgIHaV%2BISUtc44s10g9KVuUdKtyXc3vq%2F7kog%3D&reserved=0
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 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
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
> {
typedef mp_invoke_N
type;
};
using mp_q_inside_N_t = mp_quote_trait
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.
Here is my formal review of Mp11.
On Jul 15, 2017, at 4:19 AM, Bjorn Reese via Boost
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
On Wed, Jul 19, 2017 at 12:47 PM, Brook Milligan via Boost < 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
On Jul 19, 2017, at 12:41 PM, Zach Laine
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_parametertag::first().default_value(0), make_parametertag::second().default_value(1), make_parametertag::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
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
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-tp46968... Sent from the Boost - Dev mailing list archive at Nabble.com.
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?)
On Sat, Jul 22, 2017 at 9:10 PM, Peter Dimov via Boost
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
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?
6. Did you try to use the library? With what compiler? Did you have any
Quite high; should replace a lot of current boost MPL usage. 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-announce@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
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
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
On Sat, Jul 15, 2017 at 5:19 AM, Bjorn Reese via Boost < boost@lists.boost.org> wrote: [snip]
1. Should Mp11 be accepted into Boost? Please state all conditions for acceptance explicity.
MP11 should be ACCEPTED. I don't really have an opinion on the merits of
mp11 vs. Metal/Brigand/Kvasir, but I think MP11 has a home in Boost, and I'm glad it has been proposed. Apologies for the late review.
2. What is your evaluation of the design?
I really like the lightweight approach, and I especially appreciate the wide compatibility. The compatibility level is the biggest value to Boost here -- the effort required to achieve this is significant. The algorithm selection is fine. I'm not a fan of the mp_ prefix. I'm also not a fan of interfaces with "first", "second", and "third" (I prefer indices).
3. What is your evaluation of the implementation?
I think the manual unrolling of variadic templates is strange (reminds me of old C++), but I assume this is done for optimization (?). 4. What is your evaluation of the documentation?
It seems solid. I only skimmed it.
5. What is your evaluation of the potential usefulness of the library?
Useful, given its compatibility claims. I will continue to use Hana for my projects, but I would reach for this if I needed to support MSVC.
6. Did you try to use the library? With what compiler? Did you have any problems?
No.
7. How much effort did you put into your evaluation? A glance? A quick reading? In-depth study?
I skimmed the unified header and the docs. I spent a total of about 90 minutes.
8. Are you knowledgeable about the problem domain?
Yes. I am very familiar with the implementation and usage of many metaprogramming libraries and techniques. Barrett Adair
participants (18)
-
Andrey Semashev
-
Barrett Adair
-
berne@notadragon.com
-
Bjorn Reese
-
Brook Milligan
-
Bruno Dutra
-
Edouard
-
Fletcher, John P
-
Joaquin M López Muñoz
-
Louis Dionne
-
Peter Dimov
-
Peter Koch Larsen
-
peterkochlarsen
-
Robert Ramey
-
Roberto Hinz
-
vijayan
-
Vinnie Falco
-
Zach Laine