I recently encountered almost the same question, which I need to figure out if something is a kind of another, for example, if a std::vector<std::vector<float>>
is a kind of std::vector<WHATEVER>
in my open cxx reflection lib. So I implement a generic is_fuzzy_type_match_v
to check them, by using this consteval
function, you can finish it in any kind of template, even variadic parameters template.
Here the code:
#include <type_traits>
namespace noaland {
struct i_dont_care {};
template<typename T>
struct is_i_dont_care : std::false_type {};
template<>
struct is_i_dont_care<i_dont_care> : std::true_type {};
// if two type are not the same
template<typename X, typename Y>
struct is_fuzzy_type_matched {
consteval auto operator()() {
if constexpr (noaland::is_i_dont_care<X>::value || noaland::is_i_dont_care<Y>::value || std::is_same_v<X, Y>) {
return std::true_type{};
} else {
return std::false_type{};
}
}
};
template<typename X, typename Y>
inline constexpr auto is_fuzzy_type_matched_v = decltype(is_fuzzy_type_matched<X, Y>()())::value;
template<bool... R>
consteval bool conjunction() {
return (R && ...);
}
template<template<typename...> typename X, template<typename...> typename Y, typename... SUB_X, typename... SUB_Y>
struct is_fuzzy_type_matched<X<SUB_X...>, Y<SUB_Y...>> {
consteval auto operator()() {
if constexpr (!conjunction<is_fuzzy_type_matched_v<SUB_X, SUB_Y>...>()) {
return std::false_type{};
} else {
return std::true_type{};
}
}
};
}
You can use this function like this:
int main() {
static_assert(noaland::is_fuzzy_type_matched_v<std::vector<std::vector<std::vector<int>>>, std::vector<noaland::i_dont_care>>);
return 0;
}
Since I use consteval
which is a C++20 feature, you need to add --std=c++20
, or you can just change consteval
to constexpr
.
If you are interested in the content presented in this article, please take a look at my work-in-progress cxx-reflection repository on GitHub. Your stars and forks are welcome.
typedef
)? Or a specialized implementation for a certain type (likestd::vector<bool>
is)? – Lancastrianstd::vector
for a type, you shouldn't be able to do it (not in a clean way anyway). If you want to determine if a type is inherited from std::vector<XXX>, this is explicitly advised against (std::vector doesn't have a virtual destructor and SHOULD NOT be inherited, only encapsulated). If you want to determine if a class/typedef/template parameter is a std::vector<XYZ, ...>, you should use a templated traits class (see answer from jrok). – Fossstruct is_std_vector<std::vector<T,A>>
is a particularized implementation ofstruct is_std_vector
in jirok's answer). Is there a way of doing that? – Foss