Skip to content

Klasa do operacji na typach w czasie kompilacji (metaprograming)

Notifications You must be signed in to change notification settings

aronmandrella/TypePack

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 

Repository files navigation

TypePack

Zastosowanie

TypePack pozwala przechowywać wiele dowolnych typów a następnie wykonywać na nich operacje w czasie kompilacji (metaprograming).

// 'pack' to paczka typów: char, int, float, int, float, double
using pack  = TypePack<char, int, float, int, float, double>;
// 'upack' to paczka typów: char, int, float, double
using upack = TypePack<char, int, float, double>;

Przykłady

// static_assert w żadnym przykładzie niżej nie zwróci błędu

static_assert(pack::contains<double>() == true          ,"");
static_assert(pack::contains<float>() == true           ,"");
static_assert(pack::contains<long>() == false           ,"");
static_assert(pack::contains_once<char>() == true       ,"");
static_assert(pack::contains_once<float>() == false     ,"");
static_assert(pack::contains_once<long>() == false      ,"");
static_assert(pack::contains_unique() == false          ,"");
static_assert(upack::contains_unique() == true          ,"");
static_assert(pack::size() == 6                         ,"");
static_assert(pack::sum_sizeof() == 25                  ,"");
static_assert(pack::max_alignof() == 8                  ,"");
static_assert(pack::sum_sizeof_aligned() == 32          ,"");

Wszystkie funkcje

Poszczególne funkcje pozwalają np. zliczyć ile typów danego typu jest w paczce typów.

//Klasa paczek typów.
template < typename...Us >
  struct TypePack final {
    //--------------------- STALE WARIADCZNE STATYCZNE OPISUJACE PACZKE ---------------------//

    using size = std::integral_constant < size_t, sizeof...(Us) > ;
    using sum_sizeof = std::integral_constant < size_t, tpack::sum_sizeof < Us... > () > ;
    using max_alignof = std::integral_constant < size_t, tpack::max_alignof < Us... > () > ;
    using sum_sizeof_aligned = std::integral_constant < size_t, tpack::sum_sizeof_aligned < Us... > () > ;

    using is_empty = std::integral_constant < bool, sizeof...(Us) == 0 > ;

    template < typename T > using index_of = tpack::index_of < T, Us... > ;

    //Przyklad uzycia 1 : pack::size()            // ilosc elementow w paczce
    //Przyklad uzycia 2 : pack::size::value       // ilosc elementow w paczce
    //Przyklad uzycia 5 : pack::index_of<float>() // index wystepowania typu float w paczce

    //------- FUNKTORY SPRAWDZAJACE WYSTEPOWANIE DANEGO TYPU - MOZNA UZYC JAKO FILTR ------//

    template < typename T > using contains = std::integral_constant < bool, tpack::contains < T, Us... > () > ;
    template < typename T > using contains_once = std::integral_constant < bool, tpack::contains_once < T, Us... > () > ;
    template < typename T > using contains_count = std::integral_constant < size_t, tpack::contains_count < T, Us... > () > ;
    using contains_unique = std::integral_constant < bool, tpack::contains_unique < Us... > () > ;

    template < template < typename > typename T >
      using check_all = std::integral_constant < bool, tpack::check_all < T, Us... > () > ;
    template < template < typename > typename T >
      using check_any = std::integral_constant < bool, tpack::check_any < T, Us... > () > ;
    template < template < typename > typename T >
      using check_count = std::integral_constant < size_t, tpack::check_count < T, Us... > () > ;

    //Przyklad uzycia 1 : pack::contains<int>()             // 1 jesli int jest przynajmniej raz w paczce, 0 jesi nie
    //Przyklad uzycia 2 : pack2::filter<pack1::contains>()  // wynik to paczka elementow wspolnych
    //Przyklad uzycia 3 : pack3::check_all<std::is_empty>() // 1 jesli chociaz jeden typ to typ pusty

    //------- TYPY POZWALAJACE POBRAC TYP NA DANYM INDEKSIE LUB OD/WYPAKOWAC PACZKE -------//

    template < template < class... > class T > using unpack_into = T < Us... > ;
    template < typename T > using unpack_from = typename tpack::unpack_from < T > ::type;
    template < size_t Index > using get = typename tpack::get < Index, Us... > ::type;

    //Przyklad uzycia 1 : TypePack<int,char>::get<1>					// zwroci typ int
    //Przyklad uzycia 2 : TypePack<int,char>::unpack_into<std::tuple>	// zwroci typ std::tuple<int,char>
    //Przyklad uzycia 3 : TypePack<>::unpack_from<std::tuple<int,char>>	// zwroci typ TypePack<int,char>

    //------------------------ ZLOZONE OPERACJE NA PACZKACH TYPOW ------------------------//

    template < typename...Ts >
      using append = typename tpack::join < TypePack < Us... > , Ts... > ::type;

    template < size_t count >
      using remove_front = typename tpack::remove_front < count, Us... > ::type;

    template < size_t count >
      using remove_back = typename tpack::remove_back < count, Us... > ::type;

    template < template < typename > typename F >
      using filter = typename tpack::filter < F, Us... > ::type;

    template < template < typename > typename F >
      using filter_inv = typename tpack::filter_inv < F, Us... > ::type;

    template < template < typename > typename F >
      using modify = typename tpack::modify < F, Us... > ::type;

    template < size_t count >
      using divide = typename tpack::divide < count, Us... > ::type;

    template < typename...Ts >
      using contains_indexes = typename tpack::contains_indexes < TypePack < Us... > , Ts... > ::type;

    using remove_repetitions = typename tpack::remove_repetitions < Us... > ::type;

    using underlying_types = typename
    modify < std::remove_reference > ::template
    modify < std::remove_cv > ::template
    modify < std::remove_pointer > ::template
    modify < std::remove_all_extents > ;

    //Przyklad uzycia 1  : TypePack<>::append<int, TypePack<char, float>>        // zwroci typ TypePack<int,char,float>
    //Przyklad uzycia 2  : TypePack<TypePack<int>>::append<TypePack<int>>        // zwroci typ TypePack<TypePack<int>, int>
    //Przyklad uzycia 3  : TypePack<int,char,float>::filter<std::is_integral>    // zwroci typ TypePack<int,char>
    //Przyklad uzycia 4  : TypePack<int,char,float>::filter_inv<std::is_integral>// zwroci typ TypePack<float>
    //Przyklad uzycia 5  : TypePack<int,char,float>::contains_indexes<int,float> // zwroci typ std::integer_sequence<size_t, 0, 2>;
    //Przyklad uzycia 6  : TypePack<int, const float>::modify<std::add_volatile> // zwroci typ TypePack<volatile int,volatile const float>
    //Przyklad uzycia 7  : TypePack<int,float,int,char>::remove_repetitions      // zwroci typ TypePack<int,float,char>
    //Przyklad uzycia 8  : TypePack<const int, int*, int&&>::underlying_types	 // zwroci typ TypePack<int,int,int>
    //Przyklad uzycia 9  : TypePack<int,char,float>::remove_back<2>		         // zwroci typ TypePack<int>
    //Przyklad uzycia 10 : TypePack<int, long, char, float, void>::divide<2>	 // zwroci typ TypePack<TypePack<int, long>, TypePack<char, float>, TypePack<void>>

    //----------------------- FUNKCJE TYPU FOR EACH (PO KAZDYM TYPIE) ----------------------//

    template < typename Function >
      static void for_each_type(Function && f) {
        ::for_each_type < Us... > (std::forward < Function > (f));
      }

    //Przyklad uzycia 1 : TypePack<int,char>
    //      for_each_type([]{auto i, auto t}{ std::cout<<typeid(typename decltype(t)::type).name();})

    //------------------ STALE I TYPY PRZYDATNE PRZY ALOKOWANIU PAMIECI -------------------//

    //Odpowiednia zaalokowana pamiec na typy.
    using aligned_storage = tpack::aligned_storage < Us... > ;

    //------------------ FUNKCJA WYPISUJACA POZWALAJACA NA DEBUGOWANIE -------------------//

    static void _print() {
      std::cout << "List size:\t" << size() << std::endl << "Contents:\t";
      using Swallow = int[];
      (void) Swallow {
        0,
        (void(std::cout << typeid(Us).name() << ", "), 0)...
      };
      std::cout << "\n\n";
    }
  };

About

Klasa do operacji na typach w czasie kompilacji (metaprograming)

Topics

Resources

Stars

Watchers

Forks

Languages