templates - Automatically incrementing an index in the following macro generated structs in C++ -


i have template function looks this:

template <class t> void foo(t* t) {     //do stuff using:     somearray[idx]; //idx depends on t } 

there handful of possible types t, approach in unnamed namespace:

struct sentinel; template <class t> struct offsets {}; #define genidx(t,num) template <> struct offsets<t> {static const int idx = num;};  genidx(fox, 0) genidx(cat, 1) genidx(rat, 2)  genidx(sentinel, 3)  static const size_t numtypes = offsets<sentinel>::idx; 

and later on, member array somearray declared somearray[numtypes];

and foo method implemented this:

template <class t> void foo(t* t) {     typedef offsets<t> offset_t;     somearray[offset_t::idx]; //idx depends on t } 

and if needs add new type system, can add new genidx , work. nuisance if wants add, say, wolf mix, want logically appear before cat have bump remaining indices manually. wondering if there way not require numerical indices in macro, , instead let automatically sequentially generated. this, except below doesn't work:

size_t numtypes = 0; template <class t> struct offsets {}; #define genidx(t) template <> struct offsets<t> {static const int idx = numtypes++;};  genidx(fox) genidx(cat) genidx(rat) 

after numtypes correctly contain size of array. not require index management when inserting new specializations anywhere in mix , interesting, if @ least curiosity point of view, know how done.

also though of doing this, after realized don't have __counter__ on gcc version:

template <class t> struct offsets {}; #define genidx(t) \     template <> struct offsets<t> \     { \       #include boost_pp_update_counter() \       static const int idx = counter; \     }; 

but above fails because can't #include inside macro...

a c++11 solution

some includes , helper:

#include <cstddef> #include <tuple> #include <type_traits> #include <iostream>  template < typename t0, typename t1 > constexpr auto c_min(t0 p0, t1 p1) -> typename std::common_type<t0, t1>::type {     return p0 < p1 ? p0 : p1; } 

your types , "collection" of types:

struct fox {}; struct cat {}; struct rat {};  using my_types = std::tuple < fox, cat, rat >; 

two functions:

// returns size of collection constexpr std::size_t get_size() {     return std::tuple_size<my_types>::value; }   // `get_index < type > ();` returns index of type in collection  // no definition required, used suppress error messages template < typename, std::size_t > constexpr std::size_t get_index(std::integral_constant<bool, true>);  template < typename t, std::size_t t = 0 > constexpr std::size_t get_index(std::integral_constant<bool, false> = {}) {     using current = typename std::tuple_element<t, my_types>::type;     using issame = std::is_same<t, current>;      static_assert(issame{} || t+1 < get_size(),                   "unknown type: passed type not in tuple.");      using iserror = std::integral_constant< bool,                                             (issame{} || t+1 == get_size()) >;      return issame{} ? t : get_index<t, t+1>( iserror{} ); } 

usage example:

int somearray[ get_size() ] = {0};   template < class t > void foo(t* t) {     somearray[ get_index<t>() ] = 42; }   int main() {     std::cout << "array before modification: ";     for(auto const& e : somearray)     {         std::cout << e << ", ";     }     std::cout << std::endl;      struct cow {};     cow f;     foo(&f);      std::cout << "array after modification: ";     for(auto const& e : somearray)     {         std::cout << e << ", ";     }     std::cout << std::endl; } 

Comments

Popular posts from this blog

blackberry 10 - how to add multiple markers on the google map just by url? -

php - guestbook returning database data to flash -

delphi - Dynamic file type icon -