c++ - static_assert always triggering in constexpr -


i wrote following code find first index in tuple containing given type.

#include <cstdio> #include <tuple> #include <type_traits> #include <utility>  namespace detail {     template <typename t, typename tuple, std::size_t h, std::size_t... i>     constexpr std::size_t tuple_type_index_impl(tuple tup, std::index_sequence<h, i...> seq, std::size_t ret = 0) {         if (std::is_same<t, typename std::tuple_element<h, tuple>::type>::value)             ret = h;         else ret = tuple_type_index_impl<t>(tup, std::index_sequence<i...>{});         return ret;     }      template <typename t, typename tuple, std::size_t h>     constexpr std::size_t tuple_type_index_impl(tuple tup, std::index_sequence<h> seq) {         static_assert(std::is_same<t, typename std::tuple_element<h, tuple>::type>::value, "type not in tuple!");         return h;     } }  template <typename t, typename tuple> constexpr std::size_t tuple_type_index(tuple tup) {     return detail::tuple_type_index_impl<t>(tup, std::make_index_sequence<std::tuple_size<tuple>::value>{}); }  class {}; class b {}; class c {}; class d {};  std::tuple<a, b, c> abc;  int main() {      printf("b index : %zu\n", tuple_type_index<d>(abc));      system("pause");     return 0; } 

the problem have if try find index type c static_assert trigger. i'm not sure why it's going way ending function when try find index of types a or b.

if remove static_assert return values correct, return value types not in tuple.


inspired marked answer, have reworked implementation.

it available on coliru

this version should work on clang++ , g++ instead of on msvc.

i suppose problem don't write right terminal (index sequence empty) tuple_type_index_impl() function.

en passant, 0 value (in case of "type not found") isn't idea (imho) because confuse "first type".

i've modified example in following

#include <tuple> #include <utility> #include <iostream> #include <type_traits>  namespace detail  {    template <typename t, typename tuple>       constexpr std::size_t tuple_type_index_impl          (const tuple &,           const std::index_sequence<> &,           std::size_t ret = std::tuple_size<tuple>::value)        { return ret; }     template <typename t, typename tuple, std::size_t h, std::size_t ... i>       constexpr std::size_t tuple_type_index_impl          (const tuple & tup,           const std::index_sequence<h, i...> & seq,           std::size_t ret = std::tuple_size<tuple>::value)        {          return std::is_same<t, typename std::tuple_element<h, tuple>::type>::value             ? h             : tuple_type_index_impl<t>(tup, std::index_sequence<i...>{}, ret);        }  }  template <typename t, typename tuple> constexpr std::size_t tuple_type_index (const tuple & tup)  {    return detail::tuple_type_index_impl<t>       (tup, std::make_index_sequence<std::tuple_size<tuple>::value>{});  }  class {}; class b {}; class c {}; class d {};  int main()  {    std::tuple<a, b, c> abc;     std::cout << "a index: " << tuple_type_index<a>(abc) << std::endl;    std::cout << "b index: " << tuple_type_index<b>(abc) << std::endl;    std::cout << "c index: " << tuple_type_index<c>(abc) << std::endl;    std::cout << "d index: " << tuple_type_index<d>(abc) << std::endl;     return 0;  } 

give me time , try prepare simpler example.

--- edit: added example ---

you're working types, there isn't need of create , pass function tuple (and index sequences) objects.

i've prepared example based on (sfinae based) tupletypeindexhelper struct; working types use

tuple_type_index<a, std::tuple<a, b, c>>() 

or (when abc istantiation of std::tuple<a, b, c>) as

tuple_type_index<b, decltype(abc)>() 

the following example works (at least: g++ 4.9.2 , clang++ 3.5) c++11 too

#include <tuple> #include <utility> #include <iostream> #include <type_traits>  namespace detail  {    template <typename t, typename tuple, std::size_t ind>       struct tupletypeindexhelper        {          static constexpr std::size_t  dimt { std::tuple_size<tuple>::value };           template <std::size_t = ind>             static typename std::enable_if<(i >= dimt), std::size_t>::type func ()           { return dimt; }           template <std::size_t = ind>             static typename std::enable_if<(i < dimt), std::size_t>::type func ()           {             using typei = typename std::tuple_element<i, tuple>::type;              return std::is_same<t, typei>::value                ?                : tupletypeindexhelper<t, tuple, i+1u>::func();           }        };   }  template <typename t, typename tuple> constexpr std::size_t tuple_type_index ()  { return detail::tupletypeindexhelper<t, tuple, 0u>::func(); }  class {}; class b {}; class c {}; class d {};  int main()  {    using  t3 = std::tuple<a, b, c>;     std::cout << "a index:   " << tuple_type_index<a, t3>() << std::endl;    std::cout << "b index:   " << tuple_type_index<b, t3>() << std::endl;    std::cout << "c index:   " << tuple_type_index<c, t3>() << std::endl;    std::cout << "d index:   " << tuple_type_index<d, t3>() << std::endl;    std::cout << "int index: " << tuple_type_index<int, t3>() << std::endl;     std::tuple<a, b, c> abc;     std::cout << "a index: " << tuple_type_index<a, decltype(abc)>() << std::endl;    std::cout << "b index: " << tuple_type_index<b, decltype(abc)>() << std::endl;    std::cout << "c index: " << tuple_type_index<c, decltype(abc)>() << std::endl;    std::cout << "d index: " << tuple_type_index<d, decltype(abc)>() << std::endl;     return 0;  } 

Comments

Popular posts from this blog

amazon web services - S3 Pre-signed POST validate file type? -

c# - Check Keyboard Input Winforms -