Coder Social home page Coder Social logo

cpp-typelist's Introduction

cpp-typelist

#include <tuple>
#include <string>
#include <utility>
#include <variant>

#include "dhagedorn/types/typelist.hh"

using namespace dhagedorn::types;

using record = std::tuple<std::string, int, std::string, int>;
using record_field = typelist<>
    ::from<record>
    ::set
    ::push_front<std::monostate>
    ::as<std::variant>;
    // std::variant<std::monostate, std::string, int>

A functional-style typelist for C++20.

Requires a C++20 compiler. GCC 10.1.0 and newer are known to work

Use

Create a typelist with

using tl = typelist<TYPE_1, TYPE_2, ...>;

Moving types in and out of a typelist

Create a typelist by extracting the types from another type with from:

using number = std::variant<int, float, double>;
using number_types = typelist<>::from<number>;
// typelist<int, float, double>

Convert a typelist to a usable type with as:

using number_types = typelist<>::from<number>;
using number = typelist<number_types>::as<std::variant>;
// std::variant<int, float, double>

Modifying a typelist

Supported operations are:

any_of
all_of
none_of
find_if
filter
contains
sort
transform
transform_with
transform_v
set
push_back
push_front
at
slice
size
trait_adapter

I've tried to follow names from the STL and the excellent range-v3.

Unless otherwise stated, all algorithms accept a predicate of type iter_predicate:

[]<typename T>(){ return /** true/false based on T */; }`

An overloaded form is also available:

[]<typename T, std::size_t /*or auto*/ I>(){ ...; };

std type_traits can also be converted to predicates:

using only_ints = typelist<int, float, short>
    ::filter<trait_adapter<std::is_integral>>;
    // typelist<int, short>

any_of, all_of, none_of

Equivalents of the std library's

constexpr auto is_integral = typelist<int, float, char*>
    ::any_of<[]<typename T>(){ return std::is_integral_v<T>; }>;
    // true

find_if

Equivalent to std library's find_if

using is_floating_point = typelist<int, float, char*>
    ::find_if<[]<typename T>(){ return std::is_floating_point<T>; }>;
    // float

filter

Filter out unwanted types:

using only_numeric = typelist<int, float, char*>
    ::filter<[]<typename T>(){ return std::is_numeric_v<T>; }>;
    // typelist<int>

An overloaded predicate can also be used:

[]<typename T, std::size_t I, is_typelist CURRENT_LIST>[]( ...; );

CURRENT_LIST is the current value of the filtered output list.
This can be used to implement more complex filters.
See set for an example.

contains

True if the list contains the provied type:

constexpr auto has_int = typelist<int, float, char*>
    ::contains<int>;
    // true

sort

Sorts the typelist using a predicate implementing strict weak ordering:

[]<typename A, typename B>(){ return sizeof(A) < sizeof(B); };

sort<> is equivalent to calling:

using sorted = typelist<int, float, char*>::sort<[]<typename A, typename B>(){ return sizeof(A) < sizeof(B); };
// typelist<float, int, char*>
// (assuming 32 bit float, 64 bit int and pointers)

transform, transform_with, transform_v

Convert one list into another

transform expects a target templated type:

using pointy_types = typelist<int, float, char*>
    ::transform<std::shared_ptr>;
    // typelist<shared_ptr<int>, shared_ptr<float>, shared_ptr<char>>

transform_with uses the return type of its predicate as an expression to generate the new type:

using unsafe_pointy_ints = typelist<int, float, char*>
    ::transform_with<typename T>() -> T* {}>;
    // typelist<int*, float*, char**>

transform_v converts the typelist into a std::array:

constexpr std::array sizes = typelist<int, float, char*>
    ::transform_v<[]<typename T>{ return sizeof(T); }>;
    // std::array{ 4, 4, 8 }

set

Generates a set (no duplicate types):

using record = std::tuple<int, float, char*, char*, float, int>;
using any_tuple_value = typelist<>
    ::from<record>
    ::set
    ::push_back<std::monostate>
    ::as<std::variant>;
    // std::variant<std::monostate, int, float, char*>

at

Returns the type at the specified index

using first_type = typelist<int, float, char*>::at<0>; // int

slice

Returns a slice of the typelist

using subset = typelist<int, float, char*>
    ::slice<0,2>;
    // typelist<int, float>

size

Returns the number of types in the typelist

constexpr static auto size  = typelist<int, float, char*>::size // 3

Example - Generate a variant, with no duplicate types, that holds any value from a tuple

#include <tuple>
#include <utility>
#include <variant>

#include "typelist.hh"

using namespace dhagedorn::types;

using record = std::tuple<std::string, int, std::string, int>;
using record_field = typelist<>
    ::from<record>
    ::set
    ::push_front<std::monostate>
    ::as<std::variant>; // std::variant<std::monostate, std::string, int>

record_field tuple_runtime_get(std::size_t index, const std::tuple& rec) {
    record_field out;

    [&]<auto ...INDICES>(std::index_sequence<INDICES...>) {
        auto test_element = [&]<auto I>() {
            if (index == I) {
                out = std::get<I>(rec);
            }
        };

        ((test_element.template operator()<INDICES>()) , ...);
    }(std::make_index_sequence<std::tuple_size_v<record>>());

    return out;
}

record row{"a", 1, "b", 2};
std::string value = std::get<std::string>(tuple_runtime_get(0, row));

API Samples

see sample.cc

   using list = types::typelist<double, float, int, char, int, char, float, double>;
    constexpr auto size = list::size;
    constexpr auto has_double = list::any_of<[]<typename T>(){ return std::is_same_v<T,double>; }>;
    constexpr auto is_mathy = list::any_of<[]<typename T>(){ return std::is_integral_v<T> || std::is_floating_point_v<T>; }>;
    constexpr auto is_not_stringy = list::none_of<[]<typename T>(){ return std::is_same_v<T, std::string>; }>;
    constexpr auto has_int = list::contains<int>;
    constexpr auto has_int2 = list::any_of<types::trait_predicate<std::is_integral>>;
    using with_string = list::push_back<std::string>;
    using with_void = list::push_front<void>;
    using set = list::set;
    using no_floats = list::filter<[]<typename T>(){ return !std::is_floating_point_v<T>; }>;
    using no_floats2 = list::filter<types::trait_predicate<std::is_integral>>;
    using odds = list::filter<[]<typename T, auto I, types::is_typelist list>(){ return I%2 == 1; }>;
    using sliced = list::slice<0,3>;
    using first_integral = list::find_if<[]<typename T>(){ return std::is_integral_v<T>; }>;
    using first_type = list::at<0>;
    constexpr auto sizes = list::transform_v<[]<typename T>(){ return sizeof(T); }>;
    constexpr auto indices = list::transform_v<[]<typename T, auto I>(){ return I; }>;
    using pointy = list::transform_with<[]<typename T>() -> T* { return nullptr; }>;
    using safe_pointy = list::transform<std::shared_ptr>;
    using sorted = list::sort<>;
    using sorted_backwards = list::sort<[]<typename A, typename B>(){ return sizeof(B) < sizeof(A); }>;
    using variant = list::as<std::variant>;
    using from_variant = list::from<variant>;

Evaluates to:

list:                dhagedorn::types::typelist<double, float, int, char, int, char, float, double>
size:                8
has_double:          true
is_mathy:            true
is_not_stringy:      true
has_int:             true
has_int2:            true
with_string:         dhagedorn::types::typelist<double, float, int, char, int, char, float, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >
with_void:           dhagedorn::types::typelist<void, double, float, int, char, int, char, float, double>
set:                 dhagedorn::types::typelist<double, float, int, char>
no_floats:           dhagedorn::types::typelist<int, char, int, char>
no_floats2:          dhagedorn::types::typelist<int, char, int, char>
odds:                dhagedorn::types::typelist<float, char, char, double>
sliced:              dhagedorn::types::typelist<double, float, int>
first_integral:      double
first_type:          double
sizes:               8, 4, 4, 1, 4, 1, 4, 8
indices:             0, 1, 2, 3, 4, 5, 6, 7
pointy:              dhagedorn::types::typelist<double*, float*, int*, char*, int*, char*, float*, double*>
safe_pointy:         dhagedorn::types::typelist<std::shared_ptr<double>, std::shared_ptr<float>, std::shared_ptr<int>, std::shared_ptr<char>, std::shared_ptr<int>, std::shared_ptr<char>, std::shared_ptr<float>, std::shared_ptr<double> >
sorted:              dhagedorn::types::typelist<char, char, float, int, int, float, double, double>
sorted_backwards:    dhagedorn::types::typelist<double, double, float, int, int, float, char, char>
variant:             std::variant<double, float, int, char, int, char, float, double>
from_variant:        dhagedorn::types::typelist<double, float, int, char, int, char, float, double>

cpp-typelist's People

Contributors

dave-hagedorn avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.