Instant compile time C++ 11 metaprogramming library

Overview

Brigand Meta-programming library

A brigand

Build Status

Build Status

Introduction

Brigand is a light-weight, fully functional, instant-compile time C++ 11 meta-programming library.

Everything you were doing with Boost.MPL can be done with Brigand. And if that's not the case, open an issue!

Learning

Should you wish to learn more, feel free to watch our Meeting C++ 2015 lightning talk!

Want more? Our CppCon 2016 presentation explains in details the library concepts and goes through two concrete usages.

If you are looking to learn the concepts of metaprogramming, have a look at our free e-book.

Tutorials

Documentation

The documentation is available here.

Contributors

We'd like to thank the following contributors, in alphabetical order

  • Odin Holmes
  • Marek Kurdej
  • Jonathan Poelen
Comments
  • brigand::sort uses a lot of RAM

    brigand::sort uses a lot of RAM

    Using brigand::sort with a roughly 100 element list on the VisualGDB IDE I get cc1plus.exe: out of memory allocating 135167 bytes error. I understand that this is probably due to the fact that the provided GCC compiler can only access 2 GB or RAM for some reason. Despite the fact that this VisualGDB limitation is stupid there may also be some optimization potential in brigand. Using my cheap old insertion sort I used before discovering brigand (see below) I get to about 300 elements before I run out of memory.

    Has there been any testing done to determine the current sort algorithm superior?

        namespace Detail {
            template<typename T_Out, template<typename, typename > class T_Pred,
                    typename T_Insert, bool B_Tag, typename ... Ts>
            struct SortInsert;
            //next is less than insert, next is not end
            template<typename ... Os, template<typename, typename > class T_Pred,
                    typename T_Insert, typename T1, typename T2, typename ... Ts>
            struct SortInsert<brigand::list<Os...>, T_Pred, T_Insert, true, T1, T2, Ts...> : SortInsert<
                brigand::list<Os..., T1>, T_Pred, T_Insert, T_Pred<T2, T_Insert>::value, T2,
                    Ts...> {};
            //next is less than insert, next is end, terminate
            template<typename ... Os, template<typename, typename > class T_Pred,
                    typename T_Insert, typename ... Ts>
            struct SortInsert<brigand::list<Os...>, T_Pred, T_Insert, true, Ts...> {
                using type = brigand::list<Os..., Ts..., T_Insert>;
            };
            //next is not less than insert, terminate
            template<typename ... Os, template<typename, typename > class T_Pred,
                    typename T_Insert, typename ... Ts>
            struct SortInsert<brigand::list<Os...>, T_Pred, T_Insert, false, Ts...> {
                using type = brigand::list<Os..., T_Insert, Ts...>;
            };
    
            template<typename TOut, template<typename, typename > class P, typename ... Ts>
            struct Sort{
                static_assert(AlwaysFalse<TOut>::value,"implausible parameters");
            };
            //out and in are not empty
            template<typename O, typename ... Os,
                    template<typename, typename > class TPred, typename TInsert,
                    typename ... Ts>
            struct Sort<brigand::list<O, Os...>, TPred, TInsert, Ts...> : Sort<
                    typename Detail::SortInsert<brigand::list<>, TPred, TInsert,
                            TPred<O, TInsert>::value, O, Os...>::type, TPred, Ts...>
            {};
            //out is empty, in is not empty
            template<typename ... Os, template<typename, typename > class TPred,
                    typename TInsert, typename ... Ts>
            struct Sort<brigand::list<Os...>, TPred, TInsert, Ts...> : Sort<
                    typename Detail::SortInsert<brigand::list<>, TPred, TInsert, false, Os...>::type,
                    TPred, Ts...>
            {};
            //in is empty
            template<typename ... Os, template<typename, typename > class P, typename ... Ts>
            struct Sort<brigand::list<Os...>, P, Ts...> {
                using type = brigand::list<Os...>;
            };
        }
    
    
        //Sort
        template<typename TList, typename TPred = LessP>
        struct Sort{
            static_assert(AlwaysFalse<TList>::value,"implausible type");
        };
    
        //empty input case
        template<template<typename, typename > class TPred>
        struct Sort<brigand::list<>, Template<TPred>> {
            using type = brigand::list<>;
        };
    
        //one element case
        template<typename T, template<typename, typename > class TPred>
        struct Sort<brigand::list<T>, Template<TPred>> {
            using type = brigand::list<T>;
        };
    
        //two or more elements case
        template<typename ... Ts, template<typename, typename > class TPred>
        struct Sort<brigand::list<Ts...>, Template<TPred>> :
            Detail::Sort<brigand::list<>, TPred,    Ts...> {};
    
        //alias
        template<typename TList, typename TPred = LessP>
        using SortT = typename Sort<TList,TPred>::type;
    
    opened by odinthenerd 40
  • If I am not mistaken find is linear, however we can do better

    If I am not mistaken find is linear, however we can do better

    If we transform<seq,pred> we essentially have a list of bools in O1, if we then create another list of bools with N true and the rest false (also O1), AND them (O1) and then compare the result to a list of all false tapes we can detect if there is a match in the half we anded with trues. This allows us to essentially do a "lower bounds" search rather than a linear search. If we use this pattern often and don't take size/2 but round up to the next power of 2 we would also achieve substantial re use of the list of bools and results of anding and comparing.

    opened by odinthenerd 29
  • remove_if has max instantiation depth issues

    remove_if has max instantiation depth issues

    Since its recursive it will only go to about 250 elemts on clang and 500 elements on MSVC. Its not so trivial to fast track though since both removing most elements and removing only a few elements are possible scenarios.

    I think the strategy of dealing with the last test results and testing the next type (and sometimes fast track) all at once strategy I have been using is not so suited this time. Since we are going to do at least N instantiations fo the predicate we could just do them once with pack expantion and pass the result together with the inputs to the recursive function, that would make it easier to write the recursion and then just do pattern matching on 8 falses or 8 trues as a fast track. The problem is that the instantiation depth would then be very dependent on the data and thus far less deterministic.

    What do you guys think?

    On a side note I wonder if exploiting the fact that x{(Ts*)0...} could be either a call to a constructor with a variadic pack if types are different or a call to a constructor with an initializer list when all type are the same could add some speed to all or none.

    
    struct AllSameType {
        bool value;
        constexpr AllSameType(...) :value{ false } {}
        template<typename T>
        constexpr AllSameType(std::initializer_list<T>) : value{ true } {}
    };
    
    template<typename...Ts>
    constexpr bool all_same() {
        return AllSameType{ ((Ts*)0)... }.value;
    }
    
    static_assert(all_same<int, int, int>(), "");
    static_assert(!all_same<bool, int, float>(), "");
    
    question 
    opened by odinthenerd 27
  • implement cascading and variadic lambdas

    implement cascading and variadic lambdas

    #177 was getting super full so I split it into greedy 'call' which is #185 and this thread.

    In essence a TMP lambda is a tree of nested metafunctions, in other words a tree of types. If we start at the root unwrapping the first type we will find a lazy metafunction containing a variadic pack of types. each of these types will fit one of four catagories: a bound argument wrapped with pin<>, a plaeholder like _1, another metafunction or a lambda wrapped in call or lcall. pin<> arguements are simply unwrapped, placeholders are swapped out, metafunctions are called recursively and lambdas are unwrapped and executed by their surrounding metafunctions. The inner working of this can be seen here, its actually quite simple (without all the fast tracks which will follow). Now with that as a foundation we still need a method of accessing the parents arguements from a child lambda when cascading. In the example transform<l,lazy::transform<_1,lcall<myF<_1,parent<_1>>>>> myF gets one parameter from the second transform and one from the first. In order to do this we need to pass the arguements from the first to the arguements of the second. This is a little harder than it may sound since myF is called in the guts of transform and our recursive walking algorithm cannot reach into transform directly and insert parameters. The trick is to swap out the lcall with our own internal wrapper called packaged_lcall which also contains a variadic pack of lists of parents parameters. This way our walker does not need to know anything about the algorithm (in this case transform) it just trusts that it will transparently pass through any arguments we hide in packaged_lcall back to our walker.

    enhancement 
    opened by odinthenerd 26
  • Fold in inherited class

    Fold in inherited class

    Hello,

    I have noticed the following issue:

    struct a{};
    struct b{};
    struct c{};
    struct mylist : brigand::list<a,b,c,c>{};
    using mylist1 = brigand::list<a,b,c,c>;
    
    using f_class_ = brigand::if_<std::is_class<brigand::_element>,
                             brigand::next<brigand::_state>,
                             brigand::_state>;
    
      static_assert(brigand::fold<mylist1, brigand::uint32_t<0>, f_class_>::value == 4, "error");
     //fails here
      static_assert(brigand::fold<mylist, brigand::uint32_t<0>, f_class_>::value == 4, "error"); 
    
    

    On the other hand the boost MPL supports this kind of traversing.

    bug wontfix 
    opened by apmanol 25
  • Write compiler detection macros

    Write compiler detection macros

    Before everyone starts using their own macros to select compilers we should probably make a compiler detect header with a few 100% correctly written macros. Off the top of my head I would request

    • is msvc
    • is GCC
    • is clang
    • is msvc2013
    • is msvc2015

    for most of the algorithms I have written so far I would have liked to make a msvc2013 version and an everything else version. Probably someone besides me should write the detection because I, as a militant macro hater, have little experience with them.

    enhancement high priority 
    opened by odinthenerd 17
  • split<typename L, typename Delim> would be nice

    split would be nice

    Since you guys are so quick at fulfilling feature requests how about:

    split<typename L, typename Delim>
    

    which would make

    using l = list<int,void,char,char,void,char,float>;
    using sl = split<l,void>;
    

    into

    list<list<int>,list<char,char>,list<char,float>>
    
    opened by odinthenerd 15
  • Start adding documentation

    Start adding documentation

    The goal of this PR is to have somewhere we can look at code and documentation and decide how we want things to look, not to be merged immediately. Basically, I think the discussion will be much more productive if we have working examples to look at.

    All I've done here is taken the main documentation from the wiki and moved it into Markdown files that Doxygen compiles. How to handle this within Standardese is an open question I haven't tried to answer. My main question for feedback is that I've added a target library to CMake called example which will compile the code snippets shown in the documentation. I haven't yet moved all the code snippets over because I wanted to get feedback before doing all of it. If you look at introduction.md you'll notice the \snippet tutorials/introduction.cpp DOXYGEN_TAG lines. These pull in the snippets from the C++ file. I think there is a lot to be said for having examples that are actually tested by CI. That way as any code is changed the required changes to the examples will be made, and hopefully the text explaining the examples too. Any objections to doing it this way?

    Second, if we do have all the examples compiled, I'm not sure we should have the #includes in them. I think having people include the brigand.hpp file is the best way to go. The primary motivation here is that otherwise we would really need one C++ file for each example to test the headers being included are correct. Having hundreds of C++ files I think will be too burdensome given that it could be avoided quite easily. Thoughts on this?

    Third, I was planning to rework the order of the documentation and add a fairly extensive "intro to TMP" section. A good introduction to the different concepts and how one should think about things at compile time is something I found was hard to find (I couldn't find anything, but the internet is vast), so I think having an intro to TMP would be very valuable. It would probably also give us another advantage in the Boost submission process.

    I want to get the ball rolling on how we want things documented since I've started adding continuations and will be documenting that as I go.

    opened by nilsdeppe 13
  • Optimized sort

    Optimized sort

    using list = brigand::sort<brigand::range<int, 0, SIZE>>;
    

    gcc-5.4.0:

    | Size = | 10 | 100 | 200 | 300 | 500 | | --- | --- | --- | --- | --- | --- | | before | 0.07s - 26M | 0.42s - 148M | 1.19s - 344M | 2.28s - 609M | 4.00s - 1011M | | after | 0.05s - 19M | 0.16s - 45M | 0.38s - 94M | 0.66s - 152M | 1.11s - 245M | | gain | 28% - 24% | 61% - 69% | 68% - 72% | 71% - 75% | 72% - 75% |

    clang-3.8.0:

    | Size = | 10 | 100 | 200 | 300 | 500 | | --- | --- | --- | --- | --- | --- | | before | 0.09s - 40M | 0.26s - 54M | 0.66s - 95M | 1.38s - 180M | 2.49s - 321M | | after | 0.09s - 40M | 0.21s - 50M | 0.48s - 73M | 0.78s - 101M | 1.27s - 145M | | gain | 0% - 0% | 19% - 6% | 27% - 23% | 43% - 43% | 48% - 54% |

    using list = brigand::sort<brigand::reverse_range<int, SIZE, 0>>;
    

    gcc-5.4.0:

    | Size = | 10 | 100 | 200 | 300 | 500 | | --- | --- | --- | --- | --- | --- | | before | 0.05s - 21M | 0.25s - 83M | 0.46s - 152M | 0.70s - 223M | 1.37s - 375M | | after | 0.05s - 19M | 0.14s - 40M | 0.26s - 65M | 0.39s - 93M | 0.71s - 161M | | gain | 0% - 7% | 43% - 51% | 43% - 56% | 44% - 58% | 48% - 56% |

    clang-3.8.0:

    | Size = | 10 | 100 | 200 | 300 | 500 | | --- | --- | --- | --- | --- | --- | | before | 0.08s - 40M | 0.19s - 48M | 0.34s - 63M | 0.52s - 81M | 0.98s - 129M | | after | 0.09s - 40M | 0.19s - 49M | 0.32s - 60M | 0.47s - 73M | 0.84s - 108M | | gain | -12% - -1% | 0% - 0% | 5% - 4% | 9% - 8% | 14% - 16% |

    using list = brigand::sort<
      brigand::transform<
        brigand::range<int, 0, SIZE>,
        brigand::bind<brigand::modulo, brigand::_1, std::integral_constant<int, 40>>
      >
    >;
    

    gcc-5.4.0:

    | Size = | 10 | 100 | 200 | 300 | 500 | | --- | --- | --- | --- | --- | --- | | before | 0.07s - 27M | 0.53s - 177M | 1.66s - 469M | 3.02s - 789M | 5.89s - 1406M | | after | 0.05s - 21M | 0.22s - 56M | 0.54s - 121M | 0.92s - 199M | 1.90s - 341M | | gain | 28% - 23% | 58% - 68% | 67% - 74% | 69% - 74% | 67% - 75% |

    clang-3.8.0:

    | Size = | 10 | 100 | 200 | 300 | 500 | | --- | --- | --- | --- | --- | --- | | before | 0.10s - 41M | 0.33s - 60M | 0.96s - 127M | 1.76s - 217M | 3.83s - 449M | | after | 0.10s - 41M | 0.26s - 55M | 0.60s - 87M | 1.04s - 131M | 1.81s - 204M | | gain | 0% - -1% | 21% - 7% | 37% - 31% | 40% - 39% | 52% - 54% |

    using list = brigand::sort<brigand::append<
      brigand::range<int, SIZE/2, SIZE>,
      brigand::range<int, 0, SIZE/2>
    >>;
    

    gcc-5.4.0:

    | Size = | 10 | 100 | 200 | 300 | 500 | | --- | --- | --- | --- | --- | --- | | before | 0.07s - 25M | 0.46s - 158M | 1.11s - 328M | 1.86s - 534M | 3.38s - 903M | | after | 0.05s - 19M | 0.17s - 45M | 0.33s - 82M | 0.63s - 139M | 1.13s - 244M | | gain | 28% - 20% | 63% - 71% | 70% - 74% | 66% - 73% | 66% - 72% |

    clang-3.8.0:

    | Size = | 10 | 100 | 200 | 300 | 500 | | --- | --- | --- | --- | --- | --- | | before | 0.09s - 40M | 0.28s - 55M | 0.61s - 86M | 1.13s - 138M | 2.02s - 245M | | after | 0.09s - 41M | 0.21s - 51M | 0.40s - 67M | 0.71s - 101M | 1.27s - 146M | | gain | 0% - 0% | 25% - 8% | 34% - 22% | 37% - 27% | 37% - 40% |

    opened by jonathanpoelen 13
  • possible performance enhancement of at

    possible performance enhancement of at

    have we tested a form of at which uses std::declval() to call at() and a "universaly convertable struct" to swallow the values?

    struct everything_converts_to_me{ 
        template<typename T>
        everything_converts_to_me(T&&){}
    };
    
    opened by odinthenerd 13
  • How to write meta-function combiner

    How to write meta-function combiner

    Let's say i want to write compose<F,G> that gimme something akin to F<G> when applied to T. or the negation fo a meta-function ?

    Looks to me the syntax is not clear (see nope in all implementation).

    opened by jfalcou 12
  • brigand::transform causes GCC and clang to never finish

    brigand::transform causes GCC and clang to never finish

    Repro :

    #include <brigand/algorithms/transform.hpp>
    
    template<typename... Args>
    struct typelist { };
    
    template <typename T>
    struct get_type
    {
      using type = typename T::type;
    };
    
    struct foobar
    {
        static const constexpr typelist<> empty{};
    };
    
    int main()
    {
        using transformed = brigand::transform<decltype(foobar::empty), get_type<brigand::_1>>;
        transformed t;
        return 0;
    }
    

    for me, with gcc-9.2 and clang-9, building never terminates (actually, it munches through my 32 gigabytes of RAM in ~1 minute and kills my machine). It works when replacing e.g. decltype(foobar::empty) with typelist<> directly.

    Any idea of where that could come from ?

    opened by jcelerier 3
  • is_set() tests fail with clang on windows

    is_set() tests fail with clang on windows

    error: static_assert failed due to requirement '!brigand::is_set<int, int>::value' "error in brigand::is_set" static_assert(!brigand::is_set<int, int>::value, "error in brigand::is_set"); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: static_assert failed due to requirement 'brigand::is_set<void, int &, int>::value' "error in brigand::is_set" static_assert(brigand::is_set<void, int&, int>::value, "error in brigand::is_set"); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: static_assert failed due to requirement 'brigand::is_set<void, const int, int>::value' "error in brigand::is_set" static_assert(brigand::is_set<void, const int, int>::value, "error in brigand::is_set"); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: static_assert failed due to requirement 'brigand::is_set<int, short, double>::value' "error in brigand::is_set" static_assert(brigand::is_set<int, short, double>::value, "error in brigand::is_set"); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: static_assert failed due to requirement 'brigand::is_set<int, short, double, float>::value' "error in brigand::is_set" static_assert(brigand::is_set<int, short, double, float>::value, "error in brigand::is_set"); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: static_assert failed due to requirement 'brigand::is_set<int, void, int &>::value' "error in brigand::is_set" static_assert(brigand::is_set<int, void, int&>::value, "error in brigand::is_set"); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~

    clang-cl.exe --version clang version 7.0.0 (trunk 328716)

    #define BRIGAND_COMP_MSVC fixes the problem. In particular I have encountered this using chromiums build environment since they moved to clang on windows.

    opened by emptywalls 4
  • Variadic and_/or_ [Feature Request]

    Variadic and_/or_ [Feature Request]

    While porting boost::mpl code to Brigand, I noticed that although and_ and or_ exist, they only support 2 arguments.

    It's fairly easy to versions taking a variadic parameter pack, using template specialization, without adding much code bloat.

    And

      template<typename... Ts>
      struct and_;
    
      template<>
      struct and_<>: true_type {};
    
      template<typename T, typename... Ts>
      struct and_<T, Ts...> : brigand::integral_constant < typename T::value_type, T::value && and_<Ts...>::value > {};
    

    Or

      template<typename... Ts>
      struct or_;
    
      template<>
      struct or_<> : brigand::integral_constant < bool, false > {};
    
      template <typename T, typename... Ts>
      struct or_<T, Ts...> : brigand::integral_constant < typename T::value_type, T::value || or_<Ts...>::value > {};
    

    If there's any interest, I can make a pull request. Thanks for the excellent library.

    opened by Alexhuszagh 7
  • folds are somewhat slow

    folds are somewhat slow

    While investigating the cause of timeouts on Metabench, I came across these:

    fold_left-gcc49 fold_right-gcc49

    It turns out that they are about as slow on GCC 6 too, so this is not only an issue with GCC 4.9. I would suggest fixing this, or I may have to prune Brigand's folds from metaben.ch (or reduce their sample size).

    opened by ldionne 19
  • should we add meta continuations to brigand?

    should we add meta continuations to brigand?

    What are meta continuations? The basic concept is that rather than having templated structs which contain both algorithm and the data being worked one uses a templated struct for the algorithms only which provides a nested template which works on the data. This pattern allows for better memoization of algorithms and faster work on data due to passing by alias rather than instantiating a type.

    Advantages: Algorithms can be composed at zero cost. In fact since we can make optimizations to composed algorithms, for example when unpacking the same list twice as is the case in partition. The ability to compose algorithms in this way allows for many more algorithms to be implemented in terms of other algorithms. For example the algorithm filter is just a transform and then a join and then a "listify" (listify is a contination which makes a list from the input parameters) but if we swap out the last step with a "count" (count is a continuation wrapper around sizeof...(Ts)) then we have a count_if. This kind of composition would be far slower with other paradigms than the hand written equivalent count_if but with continuation style this becomes a viable solution. The real advantage I see is that the user profits from this composability as well. Initial use of this in kvasir::bit has shown that the ability to compose arbitrary algorithms can make a 10 fold improvement in the speed of complex calculations.

    Disadvantages: Although this pattern does work on clang 3.0+ GCC 4.7+ and MSVC2017 I just can't get it to work on MSVC2015. Surprisingly I can't think of anything which would be broken if we swapped out all of brigands guts for kvasir::mpl's guts (basically everything in namespace mpl::c). We can implement brigands sequence type agnostic behavior easily since kvasir::mpl does not use any lists under the hood in most algorithms any way and the last listification step could be configured to be the type of the sequence which brigands front end matched. Brigand lambdas could also be wrapped up in a continuation and just work as a predicate in kvasir::mpl algorithms. That being said I've been coding too long to believe there will not be some weird shit that only comes to light after we are 90% done with porting.

    opened by odinthenerd 4
Releases(1.3.0)
  • 1.3.0(Nov 13, 2016)

    This new release brings significant performance enhancements, an updated documentation.

    The calling mechanism has been greatly reworked thanks to the contribution of @porkybrain.

    We did our best to preserve compatibility with MSVC 2013 and ICC, however these compilers are no longer 100% supported. If you are using MSVC 2013, we encourage you to upgrade to MSVC 2015 or newer.

    New features

    • Brand new calling mechanism. More information in the documentation.
    • Macros to distinguish MSVC 2013 and MSVC 2015.
    • Support for erase and has_key in map.
    • Support for Cuda and Intel.
    • Static assertion to prevent invalid reverse_range<> input.

    Improvements

    You should notice an overall compilation time reduction, and especially in these algorithms:

    • all
    • none
    • map::insert
    • range
    • sort

    You may also no

    Fixes

    • Removed trigraphs.
    • Fixed a number of MSVC 2013 incompatibilities.
    • Predicate was not passed along with merge.
    • Fixed count_if issues.
    Source code(tar.gz)
    Source code(zip)
  • 1.2.0(May 8, 2016)

    This new release brings new features, fixes and compilation speed improvements.

    Thanks a lot to all our contributors and users!

    New features

    • New split_at algorithm
    • New pop_back_n and pop_front_n functions
    • New keys_as_sequence, values_as_sequence and as_sequence functions
    • New index_of and index_if functions
    • Added basic compiler detection macros

    Improvements

    The following functions have been optimized for reduced compilation time and memory usage:

    • at_c
    • back
    • find
    • is_set
    • make_sequence
    • map functions
    • remove
    • set functions
    • sort

    Fixes

    • The standalone header is now correctly updated at each build
    • Fixed algorithms that didn't work with types other than brigand::list
    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(Jan 12, 2016)

    Brigand can now do everything you did (unless null or forbidden by law) with Boost.MPL except with faster compilation speed!

    • Fixed a couple of lambda, bind and quote issues
    • Added support for split
    • Added support for insertions in maps
    • Added sort
    • Bitwise operators
    • Improved fold implementation
    • Made algorithms (optionally) lazy

    And much more!

    Source code(tar.gz)
    Source code(zip)
  • 1.0.0(Sep 24, 2015)

Owner
Edouard A.
Edouard A.
Selective Compile-Time Reflection for C++

Introspective Some quotes from StackOverflow regarding reflection in C++: "Inspection by iterating over members of a type, enumerating its methods and

Josip Palavra 26 Mar 10, 2022
This repository is a summary of the basic knowledge of recruiting job seekers and beginners in the direction of C/C++ technology, including language, program library, data structure, algorithm, system, network, link loading library, interview experience, recruitment, recommendation, etc.

?? C/C++ 技术面试基础知识总结,包括语言、程序库、数据结构、算法、系统、网络、链接装载库等知识及面试经验、招聘、内推等信息。This repository is a summary of the basic knowledge of recruiting job seekers and beginners in the direction of C/C++ technology, including language, program library, data structure, algorithm, system, network, link loading library, interview experience, recruitment, recommendation, etc.

huihut 25.8k Sep 16, 2022
Minimal Linux Live (MLL) is a tiny educational Linux distribution, which is designed to be built from scratch by using a collection of automated shell scripts. Minimal Linux Live offers a core environment with just the Linux kernel, GNU C library, and Busybox userland utilities.

Minimal Linux Live (MLL) is a tiny educational Linux distribution, which is designed to be built from scratch by using a collection of automated shell scripts. Minimal Linux Live offers a core environment with just the Linux kernel, GNU C library, and Busybox userland utilities.

John Davidson 1.3k Sep 20, 2022
C++ standard library reference

Information This is source package for Cppreference C++ standard library reference documentation available at http://en.cppreference.com. If there is

Povilas Kanapickas 346 Sep 14, 2022
A cheatsheet of modern C++ language and library features.

C++20/17/14/11 Overview Many of these descriptions and examples come from various resources (see Acknowledgements section), summarized in my own words

Anthony Calandra 14.8k Sep 21, 2022
A library of language lexers for use with Scintilla

README for Lexilla library. The Lexilla library contains a set of lexers and folders that provides support for programming, mark-up, and data languag

Scintilla 76 Sep 14, 2022
This is a simple UNITEST to test the implementation of the the various container types of the C++ standard template library

ft_container UNITest. This is a simple UNITEST to test the implementation of the the various container types of the C++ standard template library that

Mohamed AMOUSSAOUI 40 Sep 17, 2022
Feature-rich C99 library for memory scanning purposes, designed for Windows running machines, meant to work on both 32-bit and 64-bit portable executables. Has a modern C++ wrapper.

memscan Feature-rich C99 library for memory scanning purposes, designed for Windows running machines, meant to work on both 32-bit and 64-bit portable

cristei 14 Aug 24, 2022
A single file C++ header-only minizip wrapper library

cpp-zipper A single file C++ header-only minizip wrapper library This code is based on 'Making MiniZip Easier to Use' by John Schember. https://nachti

null 6 Sep 10, 2022
C++20 Concepts IO library which is 10x faster than stdio and iostream

fast_io fast_io is a new C++20 library for extremely fast input/output and aims to replace iostream and cstdio. It is header-only (module only in the

null 153 Feb 16, 2022
Modern, header-only, compact and cross platform C++ network/sockets library

cpp-net-lib Modern, header-only, compact and cross-platform C++ network/sockets library. Don't mind the crappy name, I suck at naming things. Why? I n

Marc 10 Jul 20, 2022
C++98 library that encapsulates memory-mapped-files for POSIX or Windows

Memory-Mapped File C++ Library Tutorial and Reference Purpose This is a library, for the C++98 language and its successive versions, to handle files a

Carlo Milanesi 80 Feb 10, 2022
Connect 4 clone written with c++ with the RSGL library. Based on my connect 4 clone written in python/pygame and my SDL port of that same repo. Along with 3DS support by SaCode

RSGL-Connect-4 Building linux git clone https://github.com/RSGL-Org/RSGL-Connect-4.git cd RSGL-Connect-4 make ./Connect4 Bulding 3ds (3ds support

RSGL 2 Dec 11, 2021
C++ Type Traits for Smart Pointers that are not included in the standard library, containing inheritance detection and member detection.

Smart Pointer Type Trait ?? A simple, header-only cpp library implementing smart pointer type traits. You can easily compile your code diffrently depe

Woon2 12 Sep 14, 2022
High performance library for creating, modiyfing and parsing PDF files in C++

Welcome to PDF-Writer. A Fast and Free C++ Library for Creating, Parsing an Manipulating PDF Files and Streams. Documentation is available here. Proje

gal kahana 658 Sep 20, 2022
A pytorch implementation of instant-ngp, as described in Instant Neural Graphics Primitives with a Multiresolution Hash Encoding.

torch-ngp A pytorch implementation of instant-ngp, as described in Instant Neural Graphics Primitives with a Multiresolution Hash Encoding. Note: This

hawkey 748 Sep 21, 2022
A compile-time enabled Modern C++ library that provides compile-time dimensional analysis and unit/quantity manipulation.

mp-units - A Units Library for C++ The mp-units library is the subject of ISO standardization for C++23/26. More on this can be found in ISO C++ paper

Mateusz Pusz 639 Sep 21, 2022
Instant Kubernetes-Native Application Observability

Pixie gives you instant visibility by giving access to metrics, events, traces and logs without changing code.

Pixie Labs 3.8k Sep 20, 2022
Bitweb is an experimental digital currency that enables instant payments to anyone, anywhere in the world.

Bitweb is an experimental digital currency that enables instant payments to anyone, anywhere in the world.

Bitweb Project 12 Jul 1, 2022