c++11 - C++ How to make an std::tuple type based on partial specializations? -


i have template integer parameter, base template disabled static_assert() this. (i want specialization forms; want argument passed template prohibited except arguments)

template<itemid item_id> struct itemtemplate{     static_assert(item_id == -1,"cann't use unspecialized itemtemplate!");     static itemid id{ std::numeric_limits<itemid>::max() };     //... }; 

i have several specializations form template (i add or delete of them)

template<> struct itemtemplate<1>{     static constexpr itemid id{1};     //.. }; template<> struct itemtemplate<2>{     static constexpr itemid id{2};     //... }; 

now want create std::tuple initialised available types. in above example, itemtemplate<1> , itemtemplate<2>, not itemtemplate<3> , other non-specialized types. how achieve this?

i see way if forget static_assert() denial way , define only specializations of itemtemplate.

the following simplified example define specializations of foo , foo generic struct remain undefined.

template <std::size_t> struct foo;  template <> struct foo<2u> {}; template <> struct foo<3u> {}; template <> struct foo<5u> {}; template <> struct foo<7u> {}; 

now need detect if type defined or not; example, following

template <typename t, std::size_t = sizeof(t)> std::true_type existh (int);  template <typename> std::false_type existh (long);  template <typename t> using exist = decltype(existh<t>(0)); 

that is: exist<foo<0>>::value false , exist<foo<2>>::value true.

now need list (usable compile time) of indexes of foo specialization defined lower limit (zero, example) upper limit.

you can obtain with

template <std::size_t i, std::size_t topi, typename,           bool = (i == topi) || exist<foo<i>>::value> struct fooindexlist;  template <std::size_t topi, std::size_t ... ixs> struct fooindexlist<topi, topi, std::index_sequence<ixs...>, true>  { using type = std::index_sequence<ixs...>; };  template <std::size_t i, std::size_t topi, std::size_t ... ixs> struct fooindexlist<i, topi, std::index_sequence<ixs...>, true>  { using type = typename fooindexlist<i+1u, topi,                    std::index_sequence<ixs..., i>>::type; };  template <std::size_t i, std::size_t topi, std::size_t ... ixs> struct fooindexlist<i, topi, std::index_sequence<ixs...>, false>  { using type = typename fooindexlist<i+1u, topi,                    std::index_sequence<ixs...>>::type; }; 

using fooindexlist, obtaining std::tuple foo defined (from 0 upper limit) simple:

template <std::size_t ... idx> constexpr auto makefootupleh (std::index_sequence<idx...> const &)  { return std::make_tuple( foo<idx>{} ... ); }  constexpr auto makefootuple ()  { return makefootupleh(       typename fooindexlist<0u, 100u, std::index_sequence<>>::type {}); } 

in example upper limit 100 can template parameter of makefootuple().

the following full compiling example

#include <tuple> #include <utility> #include <iostream> #include <type_traits>  template <typename t, std::size_t = sizeof(t)> std::true_type existh (int);  template <typename> std::false_type existh (long);  template <typename t> using exist = decltype(existh<t>(0));  template <std::size_t> struct foo;  template <> struct foo<2u> {}; template <> struct foo<3u> {}; template <> struct foo<5u> {}; template <> struct foo<7u> {};  template <std::size_t i, std::size_t topi, typename,           bool = (i == topi) || exist<foo<i>>::value> struct fooindexlist;  template <std::size_t topi, std::size_t ... ixs> struct fooindexlist<topi, topi, std::index_sequence<ixs...>, true>  { using type = std::index_sequence<ixs...>; };  template <std::size_t i, std::size_t topi, std::size_t ... ixs> struct fooindexlist<i, topi, std::index_sequence<ixs...>, true>  { using type = typename fooindexlist<i+1u, topi,                    std::index_sequence<ixs..., i>>::type; };  template <std::size_t i, std::size_t topi, std::size_t ... ixs> struct fooindexlist<i, topi, std::index_sequence<ixs...>, false>  { using type = typename fooindexlist<i+1u, topi,                    std::index_sequence<ixs...>>::type; };   template <std::size_t ... idx> constexpr auto makefootupleh (std::index_sequence<idx...> const &)  { return std::make_tuple( foo<idx>{} ... ); }  constexpr auto makefootuple ()  { return makefootupleh(       typename fooindexlist<0u, 100u, std::index_sequence<>>::type {}); }   int main ()  {    auto ft = makefootuple();     static_assert( std::is_same<decltype(ft),                   std::tuple<foo<2u>, foo<3u>, foo<5u>, foo<7u>>>{}, "!");  } 

limits:

  • this solution works if generic foo isn't defined
  • the code c++14; if need in c++11 it's little more complicated
  • the upper limit in makefootuple() can't big number because fooindexlist recursive limited compiler's recursion limit; can bypass limit require mode code.

Comments

Popular posts from this blog

Sort a complex associative array in PHP -

vb.net - How to ignore if a cell is empty nothing -

recursion - Can every recursive algorithm be improved with dynamic programming? -