Not quite sure if my terminology is 100% correct, so here's the code:
template<class... Ts>
struct Empty { };
int main() {
using T = Empty<int, double>;
// How to check if T "contains" double?
return 0;
}
So this is specifically for types that accept multiple template types. Also this would ideally be at compile time. Bonus points if it doesn't need an object of the type.
The closest I was able to get (with help ) was this:
template <class check, class T, class... U>
constexpr bool contains_type(){
if constexpr (std::is_same_v<T, check>)
return true;
else if constexpr (sizeof...(U) > 0)
return contains_type<check, U...>();
else
return false;
}
template <class check, template<class> class TypeToCheck, class... T>
constexpr bool does_obj_contain_type(TypeToCheck<T...>) {
if constexpr (sizeof...(T) > 0)
return contains_type<check, T...>();
else
return false;
}
constexpr bool does_contain_double = does_obj_contain_type<double>(T{});
That contains C++ syntax I've never before seen, but it works. Would be neat if it wouldn't require the T{}
object. And maybe look a bit saner.
Not sure to understand what do you exactly want... but I suppose is something as
template <class check, template<class...> class TypeToCheck, class... T>
constexpr bool does_obj_contain_type(TypeToCheck<T...>) {
return (std::is_same_v<check, T> || ...);
}
// ...
using T = Empty<int, double>;
auto x = does_obj_contain_type<double>(T{});
But it's a problem if you can't instantiate an object of type T
. In the case, I suppose you can use class/struct specialization.
Something as
template <typename>
struct does_obj_contain_type;
template <template <typename...> class TTC, typename ... Ts>
struct does_obj_contain_type<TTC<Ts...>>
{
template <typename check>
static constexpr bool func ()
{ return (std::is_same_v<check, Ts> || ...); }
};
// ...
using T = Empty<int, double>;
constexpr auto x = does_obj_contain_type<T>::func<double>();
Or maybe better as a template variable value
(suggested by super: thanks!)
template <template <typename...> class TTC, typename ... Ts>
struct does_obj_contain_type<TTC<Ts...>>
{
template <typename Check>
static constexpr auto value = (std::is_same_v<Check, Ts> || ...);
};
// ...
using T = Empty<int, double>;
constexpr auto x = does_obj_contain_type<T>::value<double>;
The question has already been answered but I'll just throw in an expansion if you'd like to unwrap layers of Empty<>
s at some point.
#include <iostream>
#include <type_traits>
// non templated types
template<class check, class... Ts>
struct contains_type {
static constexpr bool value = (std::is_same_v<check, Ts> || ...);
};
// templated types
template <class check, template<class...> class TypeToCheck, class... Ts>
struct contains_type<check, TypeToCheck<Ts...>> {
static constexpr bool value =
(std::is_same_v<check, Ts> || ...) || // if "check" is templated
(contains_type<check, Ts>::value || ...); // unwrap one layer
};
// Helper variable template
template<class... Ts>
inline constexpr bool contains_type_v = contains_type<Ts...>::value;
template<class... Ts>
struct Empty { };
int main() {
using False = Empty<int, float, float, long double>;
using True = Empty<int, double, int>;
using DoubleNestFalse = Empty<Empty<int>, Empty<int, float>>;
using DoubleNestTrue = Empty<Empty<int>, Empty<double, float>>;
std::cout << std::boolalpha;
std::cout << contains_type_v<double, False> << '\n';
std::cout << contains_type_v<double, True> << '\n';
std::cout << contains_type_v<double, float> << '\n'; // false
std::cout << contains_type_v<double, int, double> << '\n'; // true
std::cout << contains_type_v<double, DoubleNestFalse> << '\n';
std::cout << contains_type_v<double, DoubleNestTrue> << '\n';
std::cout << contains_type_v<Empty<int>, DoubleNestTrue> << '\n'; // true
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.