Suppose I want to create a compile-time heterogenous container of unique types from some sequence of non-unique types. In order to do this I need to iterate over the source type (some kind of tuple
) and check whether each type already exists in my "unique" tuple.
My question is: How can I check whether a tuple (or a boost::fusion
container) contains a type?
I'm open to using either the STL or boost
.
Method 1: By using a loop: We will iterate through each items of the tuple one by one and compare it with the given value. If any value in the tuple is equal to the given value, it will return True. Else, it will return False.
You can use set. issubset or set. issuperset to check if every element in one tuple or list is in other. Show activity on this post.
#include <tuple> #include <type_traits> template <typename T, typename Tuple> struct has_type; template <typename T> struct has_type<T, std::tuple<>> : std::false_type {}; template <typename T, typename U, typename... Ts> struct has_type<T, std::tuple<U, Ts...>> : has_type<T, std::tuple<Ts...>> {}; template <typename T, typename... Ts> struct has_type<T, std::tuple<T, Ts...>> : std::true_type {};
DEMO
And an additional alias, if the trait itself should be std::true_type
or std::false_type
:
template <typename T, typename Tuple> using tuple_contains_type = typename has_type<T, Tuple>::type;
In C++17 you can do it like this:
template <typename T, typename Tuple> struct has_type; template <typename T, typename... Us> struct has_type<T, std::tuple<Us...>> : std::disjunction<std::is_same<T, Us>...> {};
In C++11 you have to roll your own or
/ disjunction
. Here's a full C++11 version, with tests:
#include <tuple> #include <type_traits> template<typename... Conds> struct or_ : std::false_type {}; template<typename Cond, typename... Conds> struct or_<Cond, Conds...> : std::conditional<Cond::value, std::true_type, or_<Conds...>>::type {}; /* // C++17 version: template<class... B> using or_ = std::disjunction<B...>; */ template <typename T, typename Tuple> struct has_type; template <typename T, typename... Us> struct has_type<T, std::tuple<Us...>> : or_<std::is_same<T, Us>...> {}; // Tests static_assert(has_type<int, std::tuple<>>::value == false, "test"); static_assert(has_type<int, std::tuple<int>>::value == true, "test"); static_assert(has_type<int, std::tuple<float>>::value == false, "test"); static_assert(has_type<int, std::tuple<float, int>>::value == true, "test"); static_assert(has_type<int, std::tuple<int, float>>::value == true, "test"); static_assert(has_type<int, std::tuple<char, float, int>>::value == true, "test"); static_assert(has_type<int, std::tuple<char, float, bool>>::value == false, "test"); static_assert(has_type<const int, std::tuple<int>>::value == false, "test"); // we're using is_same so cv matters static_assert(has_type<int, std::tuple<const int>>::value == false, "test"); // we're using is_same so cv matters
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With