[ create a new paste ] login | about

Link: http://codepad.org/egOr8REa    [ raw code | fork ]

C++, pasted on May 28:
//   file: type_list.hpp
// author: Filip Roséen <filip.roseen@gmail.com>
// source: http://b.atch.se/posts/constexpr-meta-container

#ifndef ATCH_TYPE_LIST_HPP
#define ATCH_TYPE_LIST_HPP

#include <cstddef>
#include <utility>

namespace atch {
  template<std::size_t N>
  using ic = std::integral_constant<std::size_t, N>;

  template<std::size_t... Ns>
  using iseq = std::index_sequence<Ns...>;

  template<std::size_t N>
  using make_iseq = std::make_index_sequence<N>;

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  template<class... Ts>
  struct type_list {
    using size_type = std::size_t;

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

    static constexpr size_type size () { return sizeof... (Ts); }

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

    template<size_type Idx>
    struct at {
      template<class T>
      struct wrapper { using result = T; };
      
      template<size_type N, class U, class... Us>
      struct access_helper
      {
          using result = typename std::conditional_t<
            (Idx == N), wrapper<U>, access_helper<N+1, Us...>
          >::result;
      };

      using result = typename access_helper<0, Ts..., void>::result;
    };

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

    template<class... Us>
    struct push {
      using result = type_list<Ts..., Us...>;
    };

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

    template<size_type Idx, class U>
    struct set {
      struct wrapper { using result = U; };
      
      template<size_type N>
      struct access_helper
      {
          using result = typename std::conditional_t<N!=Idx, at<N>, wrapper>::result;
      };

      template<size_type... Ns>
      static auto set_helper (iseq<Ns...>)
        -> type_list<typename access_helper<Ns>::result...>
      { }

      using result = decltype (set_helper (make_iseq<size()> ()));
    };
    
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

    struct init {
      template<size_type... Ns>
      static auto helper (iseq<Ns...>)
        -> type_list<typename at<Ns>::result...>
      ;

      using result = decltype (helper (make_iseq<size ()-1> ()));
    };
  };

} /* namespace atch */

#endif /* include guard */

//   file: meta_counter.hpp
// author: Filip Roséen <filip.roseen@gmail.com>
// source: http://b.atch.se/posts/constexpr-meta-container

#ifndef ATCH_META_COUNTER_HPP
#define ATCH_META_COUNTER_HPP

#include <cstddef>

namespace atch { namespace {

  template<class Tag>
  struct meta_counter {
    using size_type = std::size_t;

    template<size_type N>
    struct ident {
      friend constexpr size_type adl_lookup (ident<N>);
      static constexpr size_type value = N;
    };

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

    template<class Ident>
    struct writer {
      friend constexpr size_type adl_lookup (Ident) {
        return Ident::value;
      }

      static constexpr size_type value = Ident::value;
    };
    
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

    template<size_type N, class = char[noexcept(adl_lookup(ident<N> ()))?+1:-1]>
    static constexpr size_type value_reader (int, ident<N>) {
      return N;
    }

    template<size_type N>
    static constexpr size_type value_reader (float, ident<N>, size_type R = value_reader (0, ident<N-1> ())) {
      return R;
    }

    static constexpr size_type value_reader (float, ident<0>) {
      return 0;
    }

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

    template<size_type Max = 64>
    static constexpr size_type value (size_type R = value_reader (0, ident<Max> ())) {
      return R;
    }

    template<size_type N = 1, class H = meta_counter, int C = H::value()>
    static constexpr size_type next (size_type R = writer<ident<N + C>>::value) {
      return R;
    }
  };
}}

#endif /* include guard */

//   file: meta_list.hpp
// author: Filip Roséen <filip.roseen@gmail.com>
// source: http://b.atch.se/posts/constexpr-meta-container

#ifndef ATCH_META_LIST_HPP
#define ATCH_META_LIST_HPP

#include <cstddef>

namespace atch { namespace {

  template<class Tag>
  struct meta_list {
    using   counter = atch::meta_counter<meta_list<Tag>>;
    using size_type = typename counter::size_type;

    template<size_type N>
    struct ident {
      friend auto adl_lookup (ident<N>);
      friend auto adl_lookup (ident<N==0?0:1024+N>) {
        return atch::type_list<> {};
      }

      static constexpr size_type value = N;
    };

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    template<class Ident, class Value>
    struct writer {
      friend auto adl_lookup (ident<Ident::value>) {
        return Value {};
      }

      static constexpr size_type value = Ident::value;
    };

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    template<
      class State,
      class     H = meta_list,
      size_type C = H::counter::next (),
      class Ident = typename H::template ident<C>
    >
    static constexpr size_type push_state (size_type R = writer<Ident, State>::value) {
      return R;
    }

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    template<
      class     H = meta_list,
      size_type N = H::counter::value ()>
    using value_ident = typename H::template ident<N>;

    template<
      class     H = meta_list,
      class Ident = typename H::template value_ident<>
    >
    using value = decltype (adl_lookup (Ident ()));

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    template<class... Ts, class H = meta_list>
    static constexpr void push (
      size_type = push_state<
        typename H::template value<>::template push<Ts...>::result
      > ()
    ) {} 

    template<class H = meta_list>
    static constexpr void pop (
      size_type = push_state<
        typename H::template value<>::init::result
      > ()
    ) {}

    template<size_type Idx, class T, class H = meta_list>
    static constexpr void set (
      size_type = push_state<
        typename H::template value<>::template set<Idx, T>::result
      > ()
    ) {}
  };
}}

#endif /* include guard */

//   file: main.cpp
// author: Filip Roséen <filip.roseen@gmail.com>
// source: http://b.atch.se/posts/constexpr-meta-container

#include <type_traits> // std::is_same

int main () {
  using LX = atch::meta_list<class A>;

  LX::push<void, void, void, void> ();
  LX::set<0, class Hello> ();
  LX::set<2, class World> ();
  LX::pop ();

  LX::value<> x; // type_list<class Hello, void, class World>

  static_assert (
    std::is_same<
      atch::type_list<class Hello, void, class World>, LX::value<>
    >::value, "try again"
  );
}


Create a new paste based on this one


Comments: