Love template metaprogramming

Overview

Metal version godbolt.badge

Metal is a single-header C++11 library designed to make you love template metaprogramming.

Overview

#include <metal.hpp>

// First we need some Values
union x { char payload[10]; };
class y { public: char c; };
struct z { char c; int i; };

// ... from which we construct some Lists
using l0 = metal::list<>;
using l1 = metal::prepend<l0, x>;
using l2 = metal::append<l1, z>;
using l3 = metal::insert<l2, metal::number<1>, y>;

static_assert(metal::same<l1, metal::list<x>>::value, "");
static_assert(metal::same<l2, metal::list<x, z>>::value, "");
static_assert(metal::same<l3, metal::list<x, y, z>>::value, "");

// Lists are versatile, we can check their sizes...
static_assert(metal::size<l0>::value == 0, "");
static_assert(metal::size<l1>::value == 1, "");
static_assert(metal::size<l2>::value == 2, "");
static_assert(metal::size<l3>::value == 3, "");

// retrieve their elements...
static_assert(metal::same<metal::front<l3>, x>::value, "");
static_assert(metal::same<metal::back<l3>, z>::value, "");
static_assert(metal::same<metal::at<l3, metal::number<1>>, y>::value, "");

// count those that satisfy a predicate...
static_assert(metal::count_if<l3, metal::trait<std::is_class>>::value == 2, "");
static_assert(metal::count_if<l3, metal::trait<std::is_union>>::value == 1, "");

// We can create new Lists by removing elements...
using l0_ = metal::drop<l3, metal::number<3>>;
using l1_ = metal::take<l3, metal::number<1>>;
using l2_ = metal::erase<l3, metal::number<1>>;

static_assert(metal::same<l0, l0_>::value, "");
static_assert(metal::same<l1, l1_>::value, "");
static_assert(metal::same<l2, l2_>::value, "");

// by reversing the order of elements...
static_assert(metal::same<metal::reverse<l0>, metal::list<>>::value, "");
static_assert(metal::same<metal::reverse<l1>, metal::list<x>>::value, "");
static_assert(metal::same<metal::reverse<l2>, metal::list<z, x>>::value, "");
static_assert(metal::same<metal::reverse<l3>, metal::list<z, y, x>>::value, "");

// by transforming the elements...
using l2ptrs = metal::transform<metal::lazy<std::add_pointer>, l2>;
using l3refs = metal::transform<metal::lazy<std::add_lvalue_reference>, l3>;

static_assert(metal::same<l2ptrs, metal::list<x*, z*>>::value, "");
static_assert(metal::same<l3refs, metal::list<x&, y&, z&>>::value, "");

// even by sorting them...
template<class x, class y>
using smaller = metal::number<(sizeof(x) < sizeof(y))>;

using sorted = metal::sort<l3, metal::lambda<smaller>>;

static_assert(metal::same<sorted, metal::list<y, z, x>>::value, "");

// that and much more!

Quick Start

  1. Download metal.hpp
  2. #include </path/to/metal.hpp>
  3. Love template metaprogramming

Blazingly Fast

You don't need to just take my word for it, see for yourself at metaben.ch.

Portable

Metal is known to work on GCC, Clang, Visual Studio, and Xcode.

Documentation

The complete up-to-date documentation is available online.

License

This project is licensed under the MIT.

Comments
  • Sort performance and techniques

    Sort performance and techniques

    Whats up @brunocodutra . You got a very nice library going here.

    I was looking around and getting to know the library and techniques (since I'm a template noob :) ), so I decided to pick up metal::sort which is something I (should) understand and play with it.

    I took a list of 1500 reversed unique types (char[1500], char[1499] ... ) and sorted it. I takes around 5.5 seconds to do that in my machine (GCC 6.3).

    Just for fun, I implemented quick sort. Time went to 30 seconds (and can reach recursion limit - not nice).

    Anyway, I was intrigued as to some implementation choices, for example:

            template<typename x, typename y>
            struct _sort_impl<list<x, y>> {
                template<template<typename...> class expr>
                using type = if_<expr<y, x>, list<y, x>, list<x, y>>;
            };
    

    as opposed to:

            template<typename x, typename y, template<typename...> class expr>
            struct _sort_impl<list<x, y>, expr> {
                using type = if_<expr<y, x>, list<y, x>, list<x, y>>;
            };
    

    Why is that? I imagined it could have something to do with performance, so I changed the code into the second version but the compilation time went down to 4.5 seconds.

    question 
    opened by brenoguim 11
  • Investigate fast tracking for core algorithms

    Investigate fast tracking for core algorithms

    The overall performance of Metal is particularly sensitive to core algorithms such as metal::join<>, which could see vast improvements if fast tracked linear recursed instead of tree-folded (edouarda/brigand#127).

    enhancement help wanted 
    opened by brunocodutra 11
  • VC++ 19.24 issue

    VC++ 19.24 issue

    Just including metal.hpp results in a few errors with VC++ 19.24. I created an empty project and changed none of the settings except for adding an additional include directory for metal.hpp. The file I tested this with is the one from https://raw.githubusercontent.com/brunocodutra/metal/standalone/metal.hpp. I also tried to include metal.hpp from the include directory of the source tree, which resulted in the same errors.

    Source code:

    #include <metal.hpp> int main() {}

    Build log:

    1>C:\Users\Philipp\Documents\libs\metal-standalone\metal.hpp(3113,1): error C3527: 'intmax_t' is not a valid operand for 'sizeof...'. Did you mean to use 'sizeof'? 1>C:\Users\Philipp\Documents\libs\metal-standalone\metal.hpp(3113): message : see reference to alias template instantiation 'metal::join<caller<detail::if<std::integral_constantmetal::detail::int_,vs>::type,metal::list<x,y,t>...,metal::list...>::type...>' being compiled 1>C:\Users\Philipp\Documents\libs\metal-standalone\metal.hpp(3114): message : see reference to class template instantiation 'metal::detail::_replace_if<metal::list<vals...>,metal::list<std::integral_constantmetal::detail::int_,vs...>,x,y,t...>' being compiled 1>C:\Users\Philipp\Documents\libs\metal-standalone\metal.hpp(3113,1): error C2938: 'metal::join' : Failed to specialize alias template 1>C:\Users\Philipp\Documents\libs\metal-standalone\metal.hpp(3121,1): error C3527: 'intmax_t' is not a valid operand for 'sizeof...'. Did you mean to use 'sizeof'? 1>C:\Users\Philipp\Documents\libs\metal-standalone\metal.hpp(3121): message : see reference to alias template instantiation 'metal::join<caller<detail::if<std::integral_constantmetal::detail::int_,vs>::type,metal::list<>,metal::list...>::type...>' being compiled 1>C:\Users\Philipp\Documents\libs\metal-standalone\metal.hpp(3122): message : see reference to class template instantiation 'metal::detail::_replace_if<metal::list<vals...>,metal::list<std::integral_constantmetal::detail::int_,vs...>,>' being compiled 1>C:\Users\Philipp\Documents\libs\metal-standalone\metal.hpp(3121,1): error C2938: 'metal::join' : Failed to specialize alias template 1>C:\Users\Philipp\Documents\libs\metal-standalone\metal.hpp(4142,1): error C3527: 'intmax_t' is not a valid operand for 'sizeof...'. Did you mean to use 'sizeof'? 1>C:\Users\Philipp\Documents\libs\metal-standalone\metal.hpp(4142): message : see reference to alias template instantiation 'metal::join<caller<detail::if<std::integral_constantmetal::detail::int_,vs>::type,metal::list...,metal::list<>>::type...>' being compiled 1>C:\Users\Philipp\Documents\libs\metal-standalone\metal.hpp(4143): message : see reference to class template instantiation 'metal::detail::_find_index<metal::list<std::integral_constantmetal::detail::int_,vs...>,metal::list<vals...>>' being compiled 1>C:\Users\Philipp\Documents\libs\metal-standalone\metal.hpp(4142,1): error C2938: 'metal::join' : Failed to specialize alias template 1>Done building project "TestProject.vcxproj" -- FAILED.

    opened by cpreh 10
  • Feature/support large list merge (do not merge)

    Feature/support large list merge (do not merge)

    This PR is intended to share the work I have done related to the discussion in #84 . I'm working both in the suggestion from https://github.com/brunocodutra/metal/issues/84#issuecomment-458742205 and with the idea of creating an algorithm for large lists that fallback on the current algorithm (but adapted to be partial merge) when the lists are smaller.

    Upon my testing this version does not impose significant perfomance drawbacks, while allowing the sort algorithm to work to list sizes going up to 5000 (which is what I tested).

    I'm also opening the PR to have the CI to run this in different compilers.

    opened by brenoguim 9
  • need fast partitioner for nth_element

    need fast partitioner for nth_element

    I tested some more approaches to nth_element. The compilation time is dominated by the comparison of elements with the pivot in order to create the partitions. The original version (v0) is slow on GCC 9 because GCC 9 dislikes the pack expansion of the form

    join<if_<comp<vals, piv>, list<vals>, list<>>...>
    

    An obvious alternative is v1, which is based on metal::partition. I think that we can make it SFINAE-friendly in analogy to metal::min_element. However, the current implementation of metal::partition uses metal::replace_if once for the lo partition and once more for the non-lo partition. As an optimization, v2 creates both partitions at once by using a custom 20-line partitioner. It is twice as fast on both Clang 9 and GCC 9. I suggest to choose v2.

    Do you agree that the speedup of v2 over v1 is worth the extra code?

    If yes: should we change metal::partition, or should metal::nth_element come with its own custom partitioner?

    opened by ecrypa 7
  • ::value and ::type aliases?

    ::value and ::type aliases?

    Would you accept a PR that adds aliases for ::value and ::type like the modern C++ standard library provides? E.g.

    metal::same_v<t1, t2>

    instead of:

    metal::same<t1, t2>::value

    If I'm not mistaken these would be implemented with variable templates:

    namespace metal {
      template<typename... Ts>
      auto same_v = same<Ts...>::value;
    }
    

    Though I believe this requires C++14 so perhaps they would only be enabled if the compilation supports at least that standard.

    opened by dpacbach 5
  • Provide the same folder structure as the MPL

    Provide the same folder structure as the MPL

    If the same structure as that of the MPL is used, then people could really just rename from boost/mpl/... to boost/mpl2/... in their includes. Also, one advantage of a backwards compatible MPL is the fact that one does not have to relearn new stuff. The plain directory structure of the old MPL was easy to grok and I think will be expected by users of this library. Just my 0.2.

    enhancement 
    opened by ldionne 5
  • Allow building metal without documentation, examples and tests

    Allow building metal without documentation, examples and tests

    Users including metal in their projects using CMake's ExternalProject_Add, FetchContent or a git submodule with add_subdirectory might not want to build the docs, examples or tests. In fact, they might not even have the dependencies (doxygen for docs, boost for examples), which causes CMake to print a warning even though it doesn't cause build failures.

    For such users metal now provides options METAL_BUILD_DOC, METAL_BUILD_TESTS and METAL_BUILD_EXAMPLES that are ON by default, but can be turned off by consumers.

    opened by Corristo 4
  • Why is `typename` used instead of `class`?

    Why is `typename` used instead of `class`?

    template<class seq, template<class...> class expr> and friends are more concise than template<typename seq, template<typename...> class expr>. The keyword class can help to reduce the character count, which simplifies skimming through the code. In addition, it prevents some line breaks that are otherwise required by the column limit.

    Do you intentionally prefer typename for aesthetic reasons? Are there any compiler-compatibility issues in that direction?

    opened by ecrypa 4
  • implement `min_element` (benchmark linked in description)

    implement `min_element` (benchmark linked in description)

    See #73.

    Performance of Clang 8 and GCC 9 is similar (v5 refers to this version; v4 is based on metal::bind and metal::arg).

    I suspect that the most expensive operation in this version is the recursive call of typename _min_element_worker<false>::template type. The recursion processes one element per step (no fast-tracking), and each call uses O(N) template arguments. It should be more efficient to cut the list into smaller pieces, calculate the minima of the pieces, and then calculate the minima of the minima. I guess you know the tree-based lookup of kvasir as explained in this blog post from Odin Holmes?

    opened by ecrypa 3
  • Value type of true_/false_ is defined as boolean in documentation, but it is a number

    Value type of true_/false_ is defined as boolean in documentation, but it is a number

    Maybe, this issue is placed wrong. It is an issue regarding the documentation. The type of true_/false_ in the documentation is described as boolean constant, but it is a number. The documentation for eg. containsmentions the return value correctly as number. But it forwards to true_/false_. So someone could assume, that contains_resultin following code snipped is of type bool: auto contains_result = metal::contains<list, element>::value

    opened by ghost 2
  • Headers under metal/ are not installed

    Headers under metal/ are not installed

    CMake's install target only installs metal.hpp and nothing else. The documentation uses the more specific headers everywhere (i.e. #include <metal/list/accumulate.hpp> to use metal::accumulate) which suggested to me that using these is also supported.

    opened by cpreh 3
  • implement min_element

    implement min_element

    Continuation of https://github.com/brunocodutra/metal/pull/99#discussion_r331799458.

    I copied the code of fold_left because I want to benchmark old and new versions. Preliminary results can be found in the section "Change of fold left" at https://ecrypa.github.io/metal-benchmark/.

    opened by ecrypa 25
  • Document the internal workings

    Document the internal workings

    Add a section to the documentation describing some of the techniques used under the hood. It should serve as a reference for contributors, as well as a gentle introduction to template metaprogramming for the uninitiated.

    opened by brunocodutra 0
  • Consider renaming apply to unpack

    Consider renaming apply to unpack

    Generally, apply is synonymous with invoke. MPL library uses apply to invoke a metafunction or lambda. Boost.Hana's apply works just like std::invoke.

    However, your apply unpacks the elements of a list and then invokes the lambda, which I found to be surprising. It seems like unpack would be a better name and would avoid the confusion.

    question 
    opened by pfultz2 4
  • Try supporting the Intel compiler

    Try supporting the Intel compiler

    It was suggested in #59 that it shouldn't be too difficult to support the Intel compiler, given that its compliance to the C++11 is similar to that of GCC 4.7.

    opened by brunocodutra 0
Releases(v2.1.4)
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 46 Dec 27, 2022
Jinja2 C++ (and for C++) almost full-conformance template engine implementation

Jinja2С++ C++ implementation of the Jinja2 Python template engine. This library brings support of powerful Jinja2 template features into the C++ world

Jinja2C++ project 385 Dec 17, 2022
A custom,multifunctional class template for arrays which supports lambda functions for removing and selecting

C++ Array Template Class This is an implementation of a template class for storing data in any type.It includes user-friendly interface with lots of h

Ozan Armağan 2 Dec 8, 2021
kaun is a replacement for löve's built-in love.graphics module intended for 3D graphics

kaun kaun is a replacement for löve's built-in love.graphics module intended for 3D graphics. It is a Lua module you can require from a shared library

Joel Schumacher 4 Apr 5, 2021
Simple useful interoperability tests for WebRTC libraries. If you are a WebRTC library developer we'd love to include you!

Overview This project aims to be a convenient location for WebRTC library developers to perform interoperability tests. Who can Participate The projec

Aaron Clauson 106 Dec 18, 2022
Calculator that I Love O' so very much

cilo Calculator that I Love O' so very much Why C? Honestly? I enjoy programming in C and the high performance is always a bonus. The lower level of C

Timeo Sam Pochin 22 Sep 15, 2022
Organic Maps is a better fork of MAPS.ME, an Android & iOS offline maps app for travelers, tourists, hikers, and cyclists based on top of crowd-sourced OpenStreetMap data and curated with love by MAPS.ME founders.

?? Organic Maps is a better fork of MAPS.ME, an Android & iOS offline maps app for travelers, tourists, hikers, and cyclists based on top of crowd-sourced OpenStreetMap data and curated with love by MAPS.ME founders. No ads, no tracking, no data collection, no crapware.

Organic Maps 4.4k Jan 2, 2023
Love 6's Regular Expression Engine. Support Concat/Select/Closure Basic function. Hope u can enjoy this tiny engine :)

Regex_Engine Love 6's Blog Website: https://love6.blog.csdn.net/ Love 6's Regular Expression Engine Hope u can love my tiny regex engine :) maybe a fe

Love6 2 May 24, 2022
This repo contains solution of 450 DSA sheet by love babbar

450DSA This repo contains solution of 450 DSA sheet by love babbar . Here is the link for that list : https://450dsa.com/ Guidlines to be followed Onl

null 5 Aug 14, 2022
The UwU's Scripting language. Made with love for UwU Nyanny Commuwiwwy!

UwUscript UwUscript is a scripting language. Installation Prerequisite LLVM 10.0 flex and bison. CMake 3.10 Build Clone this repository. git clone htt

UwUssimo Robinson 8 Nov 28, 2022
Your standard library for metaprogramming

Boost.Hana Your standard library for metaprogramming Overview #include <boost/hana.hpp> #include <cassert> #include <string> namespace hana = boost::h

Boost.org 1.5k Jan 8, 2023
C++11 metaprogramming library

Mp11, a C++11 metaprogramming library Mp11 is a C++11 metaprogramming library based on template aliases and variadic templates. It implements the appr

Boost.org 187 Jan 9, 2023
Intuitive & Powerful C++20 consteval metaprogramming library(via value).

meta-value-list This library provides a bunch of consteval toolsets to do metaprogramming, and provides the pipeline syntactic sugar for function comb

Netcan 35 Oct 21, 2022
Intuitive & Powerful C++20 consteval metaprogramming library(via value).

meta-list This library provides a bunch of consteval toolsets to do metaprogramming, and provides the pipeline syntactic sugar for function combinatio

Netcan 35 Oct 21, 2022
A tiny metaprogramming library

Meta: A tiny metaprogramming library Meta is a tiny and header-only C++11 metaprogramming library released under the Boost Software License. Supported

Eric Niebler 272 Nov 22, 2022
Instant compile time C++ 11 metaprogramming library

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

Edouard A. 551 Dec 15, 2022
This project contains a library for C++ AST parsing, metaprogramming and reflection

Meta C++ This project contains a library for C++ AST parsing, metaprogramming and reflection. Also included is a tool for generating the necessary met

Keith Hammond 76 Dec 15, 2022
This is a C plus plus coding template for Compitative programming. This template is very optimized for the Online Judgment

C-plusplus-compitative-Programming-Template Tech We Used C++ Features Easy to compile Easy debug facility Analysised and optimized base template Steps

Alan Binu 15 Jan 27, 2022
FSD-Template - A template UE4.25 project for BP modding.

FSD-Template Project generated by Archengius' UE4 Template Generator. Reflected C++ classes generated by CheatingMuppet & Archengius' UE4SS UHT Genera

null 16 Dec 29, 2022