I'd like to request a review for mp11, a simple C++11 metaprogramming library. The library implements the approach outlined in my two articles http://pdimov.com/cpp2/simple_cxx11_metaprogramming.html http://pdimov.com/cpp2/simple_cxx11_metaprogramming_2.html and is available at https://github.com/pdimov/mp11/ It supports g++ 4.9 and above, clang 3.6 and above, msvc-12.0, 14.0, 14.1. The library is in Boost format and is intended to be placed in libs/mp11 in a Git clone of Boost. There is documentation in doc/html/mp11.html, it can be viewed locally, or with https://htmlpreview.github.io/?https://github.com/pdimov/mp11/master/doc/htm... Please excuse the lack of .css in that link. Thanks in advance for any interest, comments or suggestions.
On Mar 17, 2017, at 8:06 AM, Peter Dimov via Boost
wrote: I'd like to request a review for mp11, a simple C++11 metaprogramming library.
The library implements the approach outlined in my two articles
http://pdimov.com/cpp2/simple_cxx11_metaprogramming.html http://pdimov.com/cpp2/simple_cxx11_metaprogramming_2.html
and is available at
https://github.com/pdimov/mp11/
It supports g++ 4.9 and above, clang 3.6 and above, msvc-12.0, 14.0, 14.1.
Whats the reason for not supporting gcc 4.8?
Paul Fultz II wrote:
https://github.com/pdimov/mp11/
It supports g++ 4.9 and above, clang 3.6 and above, msvc-12.0, 14.0, 14.1.
Whats the reason for not supporting gcc 4.8?
gcc 4.7 and 4.8 almost work. 4.8 fails a single test, mp_replace_if, because it for some reason strips the const qualifiers from the elements there. gcc 4.7 fails one additional test, mp_defer, that isn't critical and the error is probably in the test itself. https://travis-ci.org/pdimov/mp11/builds/207959624 I can #ifdef the mp_replace_if test (or casually remove the top-level consts, whistling innocently and pretending not to know anything about the matter) and declare 4.8 supported, but the compiler bug seems likely enough to bite someone. msvc-12.0 is much buggier, but when it works, it doesn't produce wrong results. TL;DR they work and will likely continue to work, I just don't support them "officially" at the moment.
Le 17/03/2017 à 15:06, Peter Dimov via Boost a écrit :
I'd like to request a review for mp11, a simple C++11 metaprogramming library.
The library implements the approach outlined in my two articles
http://pdimov.com/cpp2/simple_cxx11_metaprogramming.html http://pdimov.com/cpp2/simple_cxx11_metaprogramming_2.html
and is available at
https://github.com/pdimov/mp11/
There is documentation in doc/html/mp11.html, it can be viewed locally, or with
https://htmlpreview.github.io/?https://github.com/pdimov/mp11/master/doc/htm...
Please excuse the lack of .css in that link.
Thanks in advance for any interest, comments or suggestions. Hi,
I believe that there is a missing tutorial/design rationale section that
could be filled with some parts of your articles.
About the infamous tuple_cat challenge. tuple_cat doesn't append. tuple
cat construct a tuple with the elements of its tuple-like parameters (I
know that the standard wording doesn't says that exactly, as it accepts
only standard tuple-like types - I've written a proposal so that it can
take in account any product type including every type that is supported
by structure binding. See
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0327r1.pdf).
Examples of product types that don't follow the template aliases pattern
are T[N], array
Vicente J. Botet Escriba wrote:
About the infamous tuple_cat challenge. tuple_cat doesn't append. tuple cat construct a tuple with the elements of its tuple-like parameters...
That's quite true. The tuple_cat implementation in the article is a
straightforward reimplementation of Eric's tuple_cat, to illustrate the
difference in styles. It fixes one limitation of the original, but others
remain. Specifically, it doesn't work when the arguments are const
qualified, when the tuple elements are move-only (although this is a defect
in std::get), or for tuple-likes apart from std::pair.
Fixing those defects one by one:
1. tuple
Vicente J. Botet Escriba wrote:
About your mp_count example. Compare your definition with this the HOF one
template
using mp_count_if = mp_plus ;
First, you need to keep in mind that the code in the article compiled and worked at the time on the compilers that I had available, which included Visual Studio 2013. Using mp_transform was a good way to crash MSVC and remains so to this day, which is why the implementations often inline it by hand. Second, the above doesn't work because P<T>::value is allowed to be 42.
template
using mp_count = mp_cont_if >;
This - assuming that is_same_t is a template alias - cannot be made to work.
Template aliases are evaluated eagerly and is_same_t<_1, V> gives you
mp_true or mp_false depending on whether V is _1 (the literal _1) or not.
You either have to use std::is_same<_1, V> and make the algorithms take and
evaluate such lambdas by replacing placeholders and looking at ::type, or
you need to bind or curry is_same_t. mp_bind
BTW, your mp_plus doesn't take a type list as parameter.
It doesn't. There's an annoying dilemma here as most functions are useful in
either form. mp_second<L> for instance takes a list, but mp_second
About mp_contains. I've not yet finished the second article yet. IMO, we need different concepts as we can have different implementations. I believe mp_contains is an example where we can have different implementations for type list and for type set.
It does, see mp_contains and mp_set_contains in the actual mp11 source. The latter requires the elements to be unique, although the data structure is still a list. I like Lisp.
About C++11, C++14, C++17. I believe that meta-programming can profit a lot of C++17 fold expressions.
That belief is not necessarily true, but there are places where fold expressions are obviously useful, such as mp_plus. mp_fold can also be rewritten in their terms, but the performance gains are disappointingly small, although it does considerably increase the list size limit that can be handled without the compiler crashing. We'll add BOOST_NO_CXX17_FOLD_EXPRESSIONS at some point, presumably. Support is currently a bit hard to detect as Clang doesn't define an __is_feature for it. (I already had to make creative use of fold expressions to work around a Clang 3.9+ bug with mp_find.)
Vicente J. Botet Escriba wrote:
About your mp_count example. Compare your definition with this the HOF one
template
using mp_count_if = mp_plus ; First, you need to keep in mind that the code in the article compiled and worked at the time on the compilers that I had available, which included Visual Studio 2013. Using mp_transform was a good way to crash MSVC and remains so to this day, which is why the implementations often inline it by hand.
Second, the above doesn't work because P<T>::value is allowed to be 42. I'm not sure this should be the case, but if it was, then, the predicate
Le 19/03/2017 à 12:06, Peter Dimov via Boost a écrit :
passed to transform should be a little bit adapted.
|mp_plus<|||mp_transform_f
template
using mp_count = mp_count_if >; This - assuming that is_same_t is a template alias - cannot be made to work. Template aliases are evaluated eagerly and is_same_t<_1, V> gives you mp_true or mp_false depending on whether V is _1 (the literal _1) or not.
You either have to use std::is_same<_1, V> and make the algorithms take and evaluate such lambdas by replacing placeholders and looking at ::type, or you need to bind or curry is_same_t. mp_bind
::invoke, if it existed (it's a few lines, I'll probably add it) or mp_quote ::invoke.
You know what I mean. is_same<_1,V> should be a meta-function class.
Being able to use HOF makes meta-programming code simpler.
I was not thinking on making the algorithms do any analysis of the place
holders. I was just thinking on providing some specializations
template <class T>
struct is_same<_1, T> {
template <class U>
using invoke = is_same;
};
or using something like Meta lambdas
template <class T> struct is_same<_1, T> : lambda<_1,
lazy::is_same<_1,T> {};
mp_quote
(I'm considering renaming ::invoke to something shorter such as ::fn.)
BTW, mp_quote does more than quoting. It is doing some binding. I've proposed the names it bind_front/bind_back that follows the new bind_front/bind_back for normal programming (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0356r0.html) Have you considered the possibility to provide algorithms taking HOF as well as template aliases?
BTW, your mp_plus doesn't take a type list as parameter.
It doesn't. There's an annoying dilemma here as most functions are useful in either form. mp_second<L> for instance takes a list, but mp_second
would also have been useful. Not sure what to do here.
Maybe we need both.
About mp_contains. I've not yet finished the second article yet. IMO, we need different concepts as we can have different implementations. I believe mp_contains is an example where we can have different implementations for type list and for type set.
It does, see mp_contains and mp_set_contains in the actual mp11 source. The latter requires the elements to be unique, although the data structure is still a list. I like Lisp.
Yes, I've see it now. BTW I'm missing how we build a mp set. It is with inherit<>? Could we have an empty set? Why mp11 provides two ways to insert elements in a set push_back and push_front? I guess that we can use all the other mp_ functions that work for type list with type set.
About C++11, C++14, C++17. I believe that meta-programming can profit a lot of C++17 fold expressions.
That belief is not necessarily true, but there are places where fold expressions are obviously useful, such as mp_plus. mp_fold can also be rewritten in their terms, but the performance gains are disappointingly small, although it does considerably increase the list size limit that can be handled without the compiler crashing.
We'll add BOOST_NO_CXX17_FOLD_EXPRESSIONS at some point, presumably. Support is currently a bit hard to detect as Clang doesn't define an __is_feature for it. (I already had to make creative use of fold expressions to work around a Clang 3.9+ bug with mp_find.) I understand that we are not yet ready to write portable C++17 code.
Best, Vicente
Vicente J. Botet Escriba wrote:
You know what I mean. is_same<_1,V> should be a meta-function class.
I didn't, not because I'm being deliberately obtuse, but because different metaprogramming libraries have taken different approaches to what constitutes a metafunction class. What they have in common is that they take metafunction classes (instead of template aliases as mp11 does) which they then evaluate internally with their eval/invoke primitive, but how invoke handles placeholders differs from library to library.
BTW, mp_quote does more than quoting. It is doing some binding.
Originally it did just quote, then I noticed that the extension to partial application (bind_front) is straightforward. In the simple case mp_quote<F> it still quotes.
BTW I'm missing how we build a mp set.
Usually you start with an empty mp_list<> and mp_set_push_back things into it; the other case is when you have an existing list L and convert it to a set with mp_unique<L>.
Vicente J. Botet Escriba wrote:
Have you considered the possibility to provide algorithms taking HOF as well as template aliases?
In the middle of a discussion about whether we need four metaprogramming libraries, you are asking me to provide a fifth. :-) mp11 is fundamentally based on template aliases. Yes, this is constraining for people who are accustomed to higher-order programming. The point is not to be all things to all people; higher-order programming is well covered by the other contenders in the field. I realize that this way of thinking does not sit well with some that would prefer we settle on a single library.
On Sun, Mar 19, 2017 at 6:51 PM, Vicente J. Botet Escriba via Boost < boost@lists.boost.org> wrote:
Have you considered the possibility to provide algorithms taking HOF as well as template aliases?
This is a false dilemma, these are _not_ mutually exclusive, one can have
the exact same lazy API with eager alias templates alone by using bind<>
instead.
Following is a snippet using Metal, that implements the cartesian product
of a List by itself. Notice how the upper case are in fact just lazy
adaptors to the eager algorithms metal provides (lower case letters), all
written using eager alias templates.
using namespace metal;
template
;
Bruno Dutra
participants (4)
-
Bruno Dutra
-
Paul Fultz II
-
Peter Dimov
-
Vicente J. Botet Escriba