Because nobody posted it, I'm adding one more solution based on the bool trick I've learned about here on SO:
#include<type_traits>
#include<tuple>
template<bool...>
struct check {};
template<typename U, typename... T>
constexpr bool contains(std::tuple<T...>) {
return not std::is_same<
check<false, std::is_same<U, T>::value...>,
check<std::is_same<U, T>::value..., false>
>::value;
}
int main() {
static_assert(contains<int>(std::tuple<int, char, double>{}), "!");
static_assert(contains<char>(std::tuple<int, char, double>{}), "!");
static_assert(contains<double>(std::tuple<int, char, double>{}), "!");
static_assert(not contains<float>(std::tuple<int, char, double>{}), "!");
static_assert(not contains<void>(std::tuple<int, char, double>{}), "!");
}
In terms of compile-time performance it's slower than the accepted solution, but it's worth to mention it.
In C++14 it would be even easier to write. The standard template offers already all what you need to do that in the <utility>
header:
template<typename U, typename... T>
constexpr auto contains(std::tuple<T...>) {
return not std::is_same<
std::integer_sequence<bool, false, std::is_same<U, T>::value...>,
std::integer_sequence<bool, std::is_same<U, T>::value..., false>
>::value;
}
This is not far conceptually from what std::get
does (available since C++14 for types), but note that the latter fails to compile if the type U
is present more than once in T...
.
If it fits with your requirements mostly depends on the actual problem.