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.
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
Post a Comment