Created
September 16, 2023 05:02
-
-
Save mralfarrakhan/e8cc0391f4d2e2dcb6cacea314d640ca to your computer and use it in GitHub Desktop.
Compile time linked list in C++14
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| #include <type_traits> | |
| #ifndef DEBUGM | |
| namespace comptime { | |
| namespace List { | |
| #endif | |
| // List variant for tail end. | |
| struct Nothing {}; | |
| // List implementation, adapted from https://gist.github.com/hdon/da3ce733c26651c1d340 | |
| template<int Val = 0, typename T = Nothing> | |
| struct List { | |
| using Tail = T; | |
| STC(int) value = Val; | |
| STC(size_t) len = 1 + T::len; | |
| }; | |
| template<int Val> | |
| struct List<Val, Nothing> { | |
| using Tail = Nothing; | |
| STC(int) value = Val; | |
| STC(size_t) len = 1; | |
| }; | |
| // Indexing by recursion from first element | |
| template<typename L, int I> | |
| struct Index { | |
| STC(int) value = Index<typename L::Tail, I - 1>::value; | |
| }; | |
| template<typename L> | |
| struct Index<L, 0> { | |
| STC(int) value = L::value; | |
| }; | |
| template<typename L> | |
| struct Head { | |
| using T = L; | |
| }; | |
| // Tail getter = Index<L, 1> | |
| template<typename L> | |
| struct Tail { | |
| using T = typename L::Tail; | |
| }; | |
| // Generator from template args | |
| template<int Val, int... Vals> | |
| struct From { | |
| using T = List<Val, typename From<Vals...>::T>; | |
| }; | |
| template<int Val> | |
| struct From<Val> { | |
| using T = List<Val, Nothing>; | |
| }; | |
| // Front concatenation | |
| template<typename L, int Val> | |
| struct Cons { | |
| using T = List<Val, L>; | |
| }; | |
| // Back concat. | |
| template<typename L, int Val, typename M = L, int... Vals> | |
| struct Append { | |
| using T = typename Append<typename L::Tail, Val, L, Vals..., L::value>::T; | |
| }; | |
| template<typename M, int Val, int... Vals> | |
| struct Append<Nothing, Val, M, Vals...> { | |
| using T = typename From<Vals..., Val>::T; | |
| }; | |
| // Compile time mapping | |
| // For now, feed a function-like struct F that takes one int template argument | |
| // and calculation on static const member named `value` | |
| template<typename L, template<int S> class F, typename M = L, int... Vals> | |
| struct Map { | |
| using T = typename Map<typename L::Tail, F, L, Vals..., F<L::value>::value>::T; | |
| }; | |
| template<template<int S> class F, typename M, int... Vals> | |
| struct Map<Nothing, F,M, Vals...> { | |
| using T = typename From<Vals...>::T; | |
| }; | |
| // zip two list, works like Map above | |
| // stops at the shortes list | |
| template<typename A, typename B, template<int R, int S> class F, typename M = A, typename N = B, int... Vals> | |
| struct ZipWith { | |
| using T = typename ZipWith<typename A::Tail, typename B::Tail, F, A, B, Vals..., F<A::value, B::value>::value>::T; | |
| }; | |
| template<typename B, template<int R, int S> class F, typename M, typename N, int... Vals> | |
| struct ZipWith<Nothing, B, F, M, N, Vals...> { | |
| using T = typename From<Vals...>::T; | |
| }; | |
| template<typename A, template<int R, int S> class F, typename M, typename N, int... Vals> | |
| struct ZipWith<A, Nothing, F, M, N, Vals...> { | |
| using T = typename From<Vals...>::T; | |
| }; | |
| template<template<int R, int S> class F, typename M, typename N, int... Vals> | |
| struct ZipWith<Nothing, Nothing, F, M, N, Vals...> { | |
| using T = typename From<Vals...>::T; | |
| }; | |
| #ifndef DEBUGM | |
| } | |
| } | |
| #endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <iostream> | |
| #include <typeinfo> | |
| #define DEBUGM | |
| #include "list.h" | |
| #ifndef DEBUGM | |
| using namespace comptime::List; | |
| #endif | |
| #define print(v) std::cout << #v << ": " << v << std::endl | |
| #define print_type(t) std::cout << #t << ": " << typeid(t).name() << std::endl // intelligible w/ clang | |
| template<int S> | |
| struct F { | |
| static constexpr int value = S * S; | |
| }; | |
| template<int S, int T> | |
| struct G { | |
| static constexpr int value = S * T; | |
| }; | |
| int main() { | |
| using head = From<11, 13, 15>::T; | |
| using front = Cons<head, 9>::T; | |
| using to = Append<front, 17>::T; | |
| using second = Tail<Tail<to>::T>::T; | |
| using map = Map<to, F>::T; | |
| using zipped = ZipWith<head, second, G>::T; | |
| print_type(head); | |
| print_type(front); | |
| print_type(to); | |
| print_type(second); | |
| print_type(map); | |
| print_type(zipped); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment