C++11 metaprogramming library

Overview

Mp11, a C++11 metaprogramming library

Mp11 is a C++11 metaprogramming library based on template aliases and variadic templates. It implements the approach outlined in the article "Simple C++11 metaprogramming" and its sequel.

Mp11 is part of Boost, starting with release 1.66.0. It however has no Boost dependencies and can be used standalone, as a Git submodule, for instance. For CMake users, add_subdirectory is supported, as is installation and find_package(boost_mp11).

Supported compilers

  • g++ 4.7 or later
  • clang++ 3.3 or later
  • Visual Studio 2013, 2015, 2017, 2019

Tested on Travis and Appveyor.

License

Distributed under the Boost Software License, Version 1.0.

Issues
  • Tuple transform

    Tuple transform

    Adds tuple_transform, which applies a callable to each tuple element and stores the results in another tuple. Also works with std::pair, but not with std::array.

    opened by HDembinski 23
  • Added work around for Nvidia nvcc cuda compiler >= 9.0

    Added work around for Nvidia nvcc cuda compiler >= 9.0

    I already opened aticket in the official boost tracker, but thought it is a better idea to directly provide a PR.

    While working with cuda and boost::mp11 I noticed that cuda 9 does not work with boost::mp11, even this simple application fails:

    #include <boost/mp11.hpp>
    int main() {}
    

    This seems to be a bug in the nvidia compiler >= 9, not boost, but this is a showstopper for using boost::mp11 together with a recent cuda version. Everything works fine with cuda 8. I didn't test an earlier version, but there is no C++11 before cuda 7 anyway.

    I already figured out, what fails in the background in the nvcc (details are ​here), but now also found a work around for boost::mp11:

    The problem occurs on code like this:

    template<template<class...> class F, class... T> using mp_defer = mp_if<mp_valid<F, T...>, detail::mp_defer_impl<F, T...>, detail::mp_no_type>;
    

    Everytime mp_if is used, the nvcc preprocessor tries to be "smart" and starts recursively replacing stuff so that in the end detail::mp_no_type... is given to the compiler (please don't ask why, some details are in the link above).

    I figured out I can prevent nvcc from doing this with invoking another struct inbetween like this:

    template<template<class...> class F, class... T>
    struct cuda_workaround
    {
        using type = mp_if<mp_valid<F, T...>, detail::mp_defer_impl<F, T...>, detail::mp_no_type>;
    };
    
    template<template<class...> class F, class... T>
    using mp_defer = typename cuda_workaround< F, T... >::type;
    

    This work around is needed on 5 places in the boost mp11 (see commit).

    I added an intermediate struct in the detail namespace as seen above for every case if cuda 9 is used and now my code compiles with nvcc 9.

    If the commit / PR needs adjustments to suit your style requirements, don't hesitate to ask. ;)

    opened by theZiz 19
  • clang -x cuda: fails on >>>

    clang -x cuda: fails on >>>

    The latest trunk (pre-7.0) of clang and all previous releases fail compiling a simple:

    #include <boost/mp11.hpp>
    
    int main()
    {}
    

    when compiling for cuda C++: clang -x cuda.

    The reason lies in some mismatch, probably between CUDA kernel starts parameters >>> and closing templates in combination with variadic template arguments.

    Reported in clang here: https://bugs.llvm.org/show_bug.cgi?id=37013

    This PR fixes the issue by just putting spaces in, conservatively, all places with triple+ > closing template brackets.

    opened by ax3l 17
  • Doesn't compile with Intel compiler

    Doesn't compile with Intel compiler

    Intel compiler isn't listed as supported thus this is a feature request not a bug report.

    Using the below alternative implementation (slight modification of the cppreference implementation of is_detected) for mp_valid reduces the failed tests from 9 to 2. Would it make sense to upload this with BOOST_WORKAROUND(BOOST_INTEL) as pull request? I currently have no idea how to work around the remaining issue(s). Any suggestion/help would be welcome.

    namespace detail
    {
    template<typename...> using void_t = void;
    
    template <class, template<class...> class F, class... T>
    struct mp_valid_impl : mp_false {};
    
    template <template<class...> class F, class... T>
    struct mp_valid_impl<void_t<F<T...>>, F, T...> : mp_true {};
    } // namespace detail                                                                                                                                                                                                                         
    
    template<template<class...> class F, class... T> using mp_valid = typename detail::mp_valid_impl<void, F, T...>;
    
    opened by rolandschulz 12
  • Requesting zip_tail / zip_tail_with

    Requesting zip_tail / zip_tail_with

    I'm not sure what the right name for these should be (the Python itertools module has an example for the first one that is named pairwise). These are fairly trivial to implement:

    template <typename L, template <typename...> class F>
    using mp_zip_tail_with = mp_transform<F, mp_pop_back<L>, mp_pop_front<L>>;
    
    template <typename L>
    using mp_zip_tail = mp_zip_tail_with<L, mp_list>;
    

    But seem useful enough that should come batteries included (and possibly there's a more efficient implementation that doesn't rely on mp_pop_back).

    On that note, mp_transform currently requires all the lists to have the same length. I think that's worth adding to the documentation (not really obvious, and the error if you get it wrong isn't particularly informative). Is it worth having a version of this that just takes the shortest list as zip?

    opened by brevzin 11
  • The reason behind the difference between mp11's CMakeLists.txt and other boost libs

    The reason behind the difference between mp11's CMakeLists.txt and other boost libs

    In my journey of writing a cmake script to download and make available the boost library which you can see here, I saw that mp11's CMakeLists.txt doesn't follow the other boost libraries' pattern and I wonder why?

    I know boost/cmake is not ready yet, but am I on the right path here?

    opened by fatal-err 8
  • GCC trunk no longer compiles algorithm.hpp in c++11/14 modes

    GCC trunk no longer compiles algorithm.hpp in c++11/14 modes

    GCC gives (potentially new) diagnostics https://compiler-explorer.com/z/TjjdserT1

    /opt/compiler-explorer/libs/boost_1_78_0/boost/mp11/algorithm.hpp:445:102: error: '>=' should be '> =' to terminate a template argument list
      445 | struct mp_take_c_impl<N, L<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, typename std::enable_if<N >= 10>::type>
          |                                                                                                      ^~
          |                                                                                                      > =
    /opt/compiler-explorer/libs/boost_1_78_0/boost/mp11/algorithm.hpp:445:107: error: template argument 3 is invalid
      445 | struct mp_take_c_impl<N, L<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, typename std::enable_if<N >= 10>::type>
          |                                                                                                           ^
    /opt/compiler-explorer/libs/boost_1_78_0/boost/mp11/algorithm.hpp:445:114: error: expected unqualified-id before '>' token
      445 | struct mp_take_c_impl<N, L<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, typename std::enable_if<N >= 10>::type>
          |                                                                                                                  ^
    

    The diagnostics stop compilation. Older versions of GCC do not object, and neither does c++17 or higher.

    opened by sehe 7
  • error C2672: 'boost::mp11::detail::cx_count_if': no matching overloaded function found on MSVC

    error C2672: 'boost::mp11::detail::cx_count_if': no matching overloaded function found on MSVC

    Issue description: Found Boost\libs\mp11 build error C2672 in MSVC, this issue can be reproduced on c92d2d0b6fa9ae77094416f8142a8128c0424941. Could you please take a look?

    Reproduce steps:

    1. git clone -c core.autocrlf=true --recursive ​https://github.com/boostorg/boost.git f:\Boost
    2. open a VS 2017 x86 command prompt and browse to f:\Boost
    3. .\bootstrap
    4. .\b2 headers variant=release --build-dir=..\out\x86rel address-model=32
    5. .\b2 variant=release --build-dir=..\out\x86rel address-model=32
    6. .\b2 -j4 variant=release --build-dir=..\out\x86rel libs\mp11\test

    ErrorMessage: .\boost/mp11/detail/mp_count.hpp(111): error C2672: 'boost::mp11::detail::cx_count_if': no matching overloaded function found libs\mp11\test\mp_count_if.cpp(38): note: see reference to class template instantiation 'boost::mp11::detail::mp_count_if_impl<L1,std::is_const>' being compiled libs\mp11\test\mp_count_if.cpp(38): note: see reference to alias template instantiation 'boost::mp11::mp_count_if<L1,std::is_const>' being compiled .\boost/mp11/detail/mp_count.hpp(111): error C3206: 'boost::mp11::detail::cx_count_if': invalid template argument for 'P', missing template argument list on class template 'std::is_const' .\boost/mp11/detail/mp_count.hpp(95): note: see declaration of 'boost::mp11::detail::cx_count_if' .\boost/mp11/detail/mp_count.hpp(111): error C3206: 'boost::mp11::detail::cx_count_if': invalid template argument for 'P', missing template argument list on class template 'std::is_volatile' .\boost/mp11/detail/mp_count.hpp(95): note: see declaration of 'boost::mp11::detail::cx_count_if' .\boost/mp11/detail/mp_count.hpp(111): error C3206: 'boost::mp11::detail::cx_count_if': invalid template argument for 'P', missing template argument list on class template 'std::is_pointer' .\boost/mp11/detail/mp_count.hpp(95): note: see declaration of 'boost::mp11::detail::cx_count_if' .\boost/mp11/detail/mp_count.hpp(111): error C3206: 'boost::mp11::detail::cx_count_if': invalid template argument for 'P', missing template argument list on class template 'is_even' .\boost/mp11/detail/mp_count.hpp(95): note: see declaration of 'boost::mp11::detail::cx_count_if'

    opened by QuellaZhang 7
  • feature request: mp_split

    feature request: mp_split

    I'm trying to port some software from brigand (which sadly doesn't look maintained anymore) to boost mp11 and this is the only function I need that doesn't have an equivalent in mp11.

    mp_split<L<T1_1, T1_2, ..., T1_n, S, T2_1, ..., T2_m, S, ...>, S> should be equal to L<L<T1_1, T1_2, ..., T1_n>, L<T2_1, T2_2, ..., T2_m>, ...>>

    Here's the implementation in brigand: https://github.com/edouarda/brigand/blob/master/include/brigand/algorithms/split.hpp

    opened by u3shit 6
  • Proposal mp_eval_and?

    Proposal mp_eval_and?

    This is a combination of mp_eval_if and mp_and. mp_and already shortcuts on the first substitution failure when mp_to_bool is applied to T or when the application yields mp_false. mp_eval_and would provide the same functionality for applications of meta functions F... on T.

    template <class T, template<class>class F...> using mp_eval_and = ...
    

    mp_eval_and<T, F0, F1, ...> is mp_false, if F0<T> is mp_false or a substitution failure. Otherwise it is mp_eval_and<T, F1, ...> and so on.

    Example application for mp_eval_and

    template <class T>
    using is_unsigned_integral = mp_eval_and<T, std::is_integral, std::is_unsigned>;
    
    opened by HDembinski 6
  • Fix GCC sign conversion warning

    Fix GCC sign conversion warning

    The conversion bool -> int -> std::size_t triggers GCC sign conversion warning.

    I don't know your policy about those warnings. Alternatively the CMake include path can be specified as SYSTEM.

    opened by foonathan 5
  • mp_map_find seems not working properly using g++

    mp_map_find seems not working properly using g++

    The code is at https://godbolt.org/z/KvjecnTe3. The code can be compiled if switching to clang 13.0.1, but gcc 11.2 or the trunk version fails. Interestingly, if I comment out line 22 and 23 as

     // boost::mp11::mp_list<enum_<Foo::A1>, int>,
     // boost::mp11::mp_list<enum_<Foo::A2>, double>,
    

    then gcc can successfully compile the code. Any ideas?

    opened by HanatoK 4
  • add projections to tuple operations

    add projections to tuple operations

    Assume we want to invoke tuple_for_each or tuple_apply on the keys or values of a map. We can encode our projection inside the function object passed as argument, but it would be nicer to pass a unary function as optional third argument.

    Consider this example

    template<class... Pairs>
    constexpr void reset_values1 (std::tuple<Pairs...>& map)
    {
      mp11::tuple_for_each (map, [] (auto& p) {
        p.second = 0;
      });
    }
    
    template<class... Pairs>
    constexpr void reset_values2 (std::tuple<Pairs...>& map)
    {
        auto set_zero = [] (auto& x) {
          x = 0;
        };
        auto second = [] (auto& x) -> auto& {
          return x.second;
        };
        mp11::tuple_for_each (map, set_zero, second);
    }
    

    The second implementation is more verbose because we had to write some function objects, but it enables easier composition. mp11 doesn't have useful function objects to compose with this feature, but higher order function libraries do.

    opened by marcorubini 0
  • boost::mp11::mp_list can't be used as base class for transition table within msm::front::state_machine_def

    boost::mp11::mp_list can't be used as base class for transition table within msm::front::state_machine_def

    I just wanted to modernize my code - and try to use boost::mp11::mp_list instead of boost::mpl::vector in my FSM definitions.

    Simplified code is as follows:

    #include <iostream>
    #include <boost/msm/back/state_machine.hpp>
    #include <boost/msm/front/state_machine_def.hpp>
    
    #include <boost/mp11/list.hpp>
    #include <boost/mp11/algorithm.hpp>
    #include <boost/mp11/mpl.hpp>
    
    namespace msm = boost::msm;
    
    namespace test_fsm 
    {
    struct play {};
    struct stop {};
    struct player_ : public msm::front::state_machine_def<player_>
    {
        typedef int no_exception_thrown;
        typedef int no_message_queue;
    
        struct Empty : public msm::front::state<> 
        {
            template <class Event,class FSM>   void on_entry(Event const&,FSM& ) { std::cout << "entering: Empty" << std::endl; }
            template <class Event,class FSM>   void on_exit(Event const&,FSM& ) { std::cout << "leaving: Empty" << std::endl; }
        };
        struct Playing : public msm::front::state<>
        {
            template <class Event,class FSM>    void on_entry(Event const&,FSM& ) { std::cout << "entering: Playing" << std::endl; }
            template <class Event,class FSM>    void on_exit(Event const&,FSM& ) { std::cout << "leaving: Playing" << std::endl; }
        };
    
        typedef Empty initial_state;
    
        // transition actions
        void playing(play const&)  {  }
        void stop_playing(stop const&)  {  }
        
        typedef player_ p; 
    
        struct transition_table : boost::mp11::mp_list<
                _row < Empty , play        , Playing       >,
                _row < Playing , stop        , Empty       >
        > {};
    
        // Replaces the default no-transition response.
        template <class FSM,class Event>
        void no_transition(Event const& e, FSM&,int state)
        {
            std::cout << "no transition from state " << state
                << " on event " << typeid(e).name() << std::endl;
        }
    
        typedef msm::back::state_machine<player_> player;
    
        //
        // Testing utilities.
       //
       static char const* const state_names[] = { "Empty", "Playing" };
    
        void pstate(player const& p)
       {
           std::cout << " -> " << state_names[p.current_state()[0]] << std::endl;
       }
    };
    
    }
    
    int main()
    {
        test_fsm::player p2;
        p2.start();
        p2.process_event(test_fsm::play());
        p2.process_event(test_fsm::stop()); 
        return 0;
    }
    
    

    It compiles, but produces unexpected output:

    entering: Empty
    no transition from state 0 on event N8test_fsm4playE
    no transition from state 0 on event N8test_fsm4stopE
    
    

    While - with original version (just replacing mp11::mp_list with mpl::vector) it works as expected:

    entering: Empty
    leaving: Empty
    entering: Playing
    leaving: Playing
    entering: Empty
    
    

    It also works as expected with boost::fusion::vector.

    I found one workaround - when using type-alias for defining transition table it works as expected:

        using transition_table = boost::mp11::mp_list<
                _row < Empty , play        , Playing       >,
                _row < Playing , stop        , Empty       >
        > ;
    
    

    With type-alias it also works for other types boost::mpl::vector and boost::fustion::vector.

    I am not sure what this inheritance is for, but all examples from boost::msm defines this transition tables that way.

    The problem with boost::mp11::mp_list is probably here <boost/mp11/mpl.hpp> - but I am not sure that.

    I asked the question about that on SO: https://stackoverflow.com/questions/68195912/boostmp11mp-list-cant-define-proper-transition-table-for-fsm-based-on-boost - but not get much attention.

    You can play with the problem on compiler explorer: https://godbolt.org/z/jTEnxPMTj

    The problem is not related to version of boost or compiler.

    opened by PiotrNycz 3
  • :new: Add `mp_quote_expr` to quote with lambda expressions

    :new: Add `mp_quote_expr` to quote with lambda expressions

    Problem:

    • There is no easy way to quote metafunction directly with lambda expressions.

    Solution:

    • Add mp_quote_expr.

    Note:

    • mp_quote_expr requires C++20.
    opened by krzysztof-jusiak 9
  • Requesting tuple_match_apply

    Requesting tuple_match_apply

    First sorry for the ugly name, I could not think of anything better. I know mp11 is mostly a lib for nice manipulation of lists, but one feature that really worked great for me is the tuple_for_each.

    I used it to implement nice(IMHO) dispatching on runtime value. "Problem" is that it is not optimally efficient since I am doing an equivalent of many ifs, instead of a switch or if else. Code example with basic idea is here(code is missing propagation of return value of the lambda, ignores alignment... but I hope general idea is clear).

    https://godbolt.org/z/1TscGs

    I have no idea what is the proper way to handle default case, I would suspect that there could be a tag type, but in my use I do not really need it since I cover all cases, so hard for me to judge if it would be a good addition.

    opened by libbooze 4
  • Support for lists of values

    Support for lists of values

    Mp11 is a great library to work on lists of types! However, when it comes to lists of values, one has to work around the values by converting them to types using e.g. std::integral_constant<int, 2>, so mp11 can work on lists of these values.

    The following code sadly does not compile:

    template <int... Values>
    struct List;
    
    using MyList = List<1, 2, 3>;
    using ShorterList = boost::mp11::mp_pop_front<MyList>;
    

    The workaround is to wrap the values:

    template <typename... Values>
    struct List;
    
    using MyList = List<std::integral_constant<int, 1>, std::integral_constant<int, 2>, std::integral_constant<int, 3>>;
    using ShorterList = boost::mp11::mp_pop_front<MyList>;
    

    However, then also the result ShorterList has all values wrapped in std::integral_constant, which is undesirable. This can be worked around again by unwrapping the list using something along the lines of (untested):

    template<class L>
    struct mp_unwrap_sizes_impl;
    
    template<template<class...> class L, typename... T>
    struct mp_unwrap_sizes_impl<L<T...>> {
        using type = L<T::value...>;
    };
    
    template<typename L>
    using mp_unwrap_sizes = typename mp_unwrap_sizes_impl<L>::type;
    

    But even better would be direct support for values in boost::mp11. I gave that a quick try and it seemed not too hard. If we add the following specialization for mp_pop_front_impl for example:

    namespace boost::mp11::detail {
        template<template<auto...> class L, auto T1, auto... T> // change here
        struct mp_pop_front_impl<L<T1, T...>> {
            using type = L<T...>;
        };
    }
    

    then the code example at the top compiles successfully. This specialization is a verbatim copy of the original specialization of mp_pop_front_impl except the class keyword inside the template template parameter and before T1 and T are replaced by auto, to change the type template arguments to non-type template arguments.

    The addition of such specializations for values adds a lot of value to boost::mp11 with probably small cost. Could you please consider adding such overloads to enable the use of this great library on value lists as well? Thank you very, very much!

    opened by bernhardmgruber 15
Owner
Boost.org
Boost provides free peer-reviewed portable C++ source libraries.
Boost.org
Libft is an individual project at 42 that requires us to re-create some standard C library functions including some additional ones that can be used later to build a library of useful functions for the rest of the program.

?? Index What is Libft? List of Functions Technologies ✨ What is Libft? Libft is an individual project at 42 that requires us to re-create some standa

Paulo Rafael Ramalho 7 Jan 17, 2022
Library that simplify to find header for class from STL library.

Library that simplify to find header for class from STL library. Instead of searching header for some class you can just include header with the class name.

null 6 Jun 7, 2022
Thrust is a C++ parallel programming library which resembles the C++ Standard Library.

Thrust: Code at the speed of light Thrust is a C++ parallel programming library which resembles the C++ Standard Library. Thrust's high-level interfac

NVIDIA Corporation 4k Jun 22, 2022
jkds is a modern header-only C++20 library that complements the standard library.

jkds is a modern header-only C++20 library that complements the standard library. It provides generic atypical data structures, ergonomic functional programming abstractions, and then some.

Alberto Schiabel 5 May 24, 2022
Bionic BSD-3-ClauseBionic - Google's standard library, developed for Android. BSD-3-Clause

bionic bionic is Android's C library, math library, and dynamic linker. Using bionic as an app developer See the user documentation. Working on bionic

Android Open Source Project 547 Jun 23, 2022
CloudABI's standard C library

NOTE: This project is unmaintained CloudABI is no longer being maintained. It was an awesome experiment, but it never got enough traction to be sustai

Nuxi 272 Jun 7, 2022
libcu++: The C++ Standard Library for Your Entire System

libcu++, the NVIDIA C++ Standard Library, is the C++ Standard Library for your entire system. It provides a heterogeneous implementation of the C++ Standard Library that can be used in and between CPU and GPU code.

NVIDIA Corporation 2k Jun 26, 2022
D++ Extremely Lightweight C++ Discord Library

D++ An incredibly lightweight C++ Discord library This project is in alpha stages of development. Completed so far: Websocket connection with heartbea

brainbox.cc 380 Jun 28, 2022
EASTL stands for Electronic Arts Standard C++ Template Library

EASTL stands for Electronic Arts Standard Template Library. It is an extensive and robust implementation that has an emphasis on high performance.

Electronic Arts 6.5k Jun 27, 2022
An open source standard C library that includes useful functions && (Reimplementation of libc functions + own functions).

?? LIBFT-42 : Artistic view of LIBC: ?? HOW DOES IT FEEL HAVING YOUR OWN LIB: SUBJECT : ENGLISH PDF ℹ️ What is LIBFT : This project aims to code a C l

Abdessamad Laamimi 10 Mar 24, 2022
Single-header header-only C++11 / C++14 / C++17 library for easily managing set of auto-generated type-safe flags.

Single-header header-only C++11 / C++14 / C++17 library for easily managing set of auto-generated type-safe flags. Quick start #include <bitflags/bitf

Marin Peko 69 May 4, 2022
expected lite - Expected objects in C++11 and later in a single-file header-only library

expected lite: expected objects for C++11 and later expected lite is a single-file header-only library for objects that either represent a valid value

Martin Moene 216 Jun 18, 2022
Guidelines Support Library

GSL: Guidelines Support Library The Guidelines Support Library (GSL) contains functions and types that are suggested for use by the C++ Core Guideline

Microsoft 5k Jun 20, 2022
gsl-lite – A single-file header-only version of ISO C++ Guidelines Support Library (GSL) for C++98, C++11, and later

gsl-lite: Guidelines Support Library for C++98, C++11 up metadata build packages try online gsl-lite is an implementation of the C++ Core Guidelines S

gsl-lite 741 Jun 27, 2022
optional lite - A C++17-like optional, a nullable object for C++98, C++11 and later in a single-file header-only library

optional lite: A single-file header-only version of a C++17-like optional, a nullable object for C++98, C++11 and later Contents Example usage In a nu

Martin Moene 345 Jun 20, 2022
Range library for C++14/17/20, basis for C++20's std::ranges

range-v3 Range library for C++14/17/20. This code was the basis of a formal proposal to add range support to the C++ standard library. That proposal e

Eric Niebler 3.4k Jun 27, 2022
span lite - A C++20-like span for C++98, C++11 and later in a single-file header-only library

span lite: A single-file header-only version of a C++20-like span for C++98, C++11 and later Contents Example usage In a nutshell License Dependencies

Martin Moene 396 Jun 22, 2022
string_view lite - A C++17-like string_view for C++98, C++11 and later in a single-file header-only library

string_view lite: A single-file header-only version of a C++17-like string_view for C++98, C++11 and later Contents Example usage In a nutshell Licens

Martin Moene 321 Jun 22, 2022
variant lite - A C++17-like variant, a type-safe union for C++98, C++11 and later in a single-file header-only library

variant lite: A single-file header-only version of a C++17-like variant, a type-safe union for C++98, C++11 and later Contents Example usage In a nuts

Martin Moene 208 Jun 9, 2022