I have a type named the_bad
. I want to replace that type with the_good
using a template metafunction. I expect that template metafunction to be quite complex so let's call it the_ugly
.
My problem is that the_bad
could be nested in other templates, and I want to leave the other templates and parameters untouched. Here's an example of what I mean, with an incomplete implementation of the_ugly
:
struct the_good {};
struct the_bad {};
template<typename T>
struct the_ugly_impl {
using type = T;
};
template<>
struct the_ugly_impl<the_bad> {
using type = the_good;
};
template<typename T>
using the_ugly = typename the_ugly_impl<T>::type;
// passes, yay!
static_assert(std::same_as<the_good, the_ugly<the_bad>>);
// doesn't pass
static_assert(std::same_as<std::vector<the_good>, the_ugly<std::vector<the_bad>>>);
// doesn't pass
static_assert(std::same_as<std::list<std::vector<the_good>>, the_ugly<std::list<std::vector<the_bad>>>>);
How can I fix the_ugly
so that it replaces the_bad
to the_good
at any nesting level, while keeping all other template and other template parameters untouched?
You just need to handle the template case, and have that invoke itself recursively:
template<typename T>
struct the_ugly_impl {
using type = T;
};
template<typename T>
using the_ugly = typename the_ugly_impl<T>::type;
template<>
struct the_ugly_impl<the_bad> {
using type = the_good;
};
template <template <typename...> class L, typename... Ts>
struct the_ugly_impl<L<Ts...>> {
using type = L<the_ugly<Ts>...>;
};