Get the template that is instantiated from

How can I get the template from which the type was originally created?

I would like to do the following:

struct Baz{};
struct Bar{};

template <typename T>
struct Foo {};

using SomeType = Foo<Bar>;

template <typename T>
using Template = get_template<SomeType>::template type<T>;

static_assert(std::is_same<Foo<Baz>, Template<Baz>>::value, "");

I know that I can achieve this through a partial specialization, but it makes me specialize get_templatefor each template that I want to use with it:

template <typename T>
struct get_template;

template <typename T>
struct get_template<Foo<T>>
{
    template <typename X>
    using type = Foo<X>;
};

Is there any way to limit this restriction?

+4
source share
2 answers

You can do something like this using a templated template template (should work for templates with any number of type ):

template <typename T>
  struct get_template;

template <template <class...> class Y, typename... Args>
  struct get_template<Y<Args...>> {
    template <typename... Others>
    using type = Y<Others...>;
  };

Then, to get the template:

template <typename T>
using Template = typename get_template<SomeType>::type<T>;

@Yakk, , . -, :

// Note: You need the first size_t to avoid ambiguity with the first specialization
template <template <class, size_t, size_t...> class Y, typename A, size_t... Sizes>
  struct get_template<Y<A, Sizes...>> {
    template <class U, size_t... OSizes>
    using type = Y<U, OSizes...>;
  };

... .


DEMO ( Foo std::pair):

#include <type_traits>
#include <map>

struct Bar{};

template <typename T>
struct Foo {};

using SomeType = Foo<Bar>;

template <typename T>
  struct get_template;

template <template <class...> class Y, typename... Args>
  struct get_template<Y<Args...>> {
    template <typename... Others>
    using type = Y<Others...>;
  };

template <typename T>
using Template = typename get_template<SomeType>::type<T>;

static_assert(std::is_same<SomeType, Template<Bar>>::value, "");
static_assert(std::is_same<Foo<int>, Template<int>>::value, "");

using PairIntInt = std::pair<int, int>;
using PairIntDouble = std::pair<int, double>;

template <typename U1, typename U2>
using HopeItIsPair = 
  typename get_template<PairIntDouble>::type<U1, U2>;

static_assert(std::is_same<PairIntDouble, HopeItIsPair<int, double>>::value, "");
static_assert(std::is_same<PairIntInt, HopeItIsPair<int, int>>::value, "");
+4

, . ?

#include<type_traits>
#include<utility>

template<typename V, template<typename> class T, typename U>
auto get_template(T<U>) { return T<V>{}; }

struct Baz{};
struct Bar{};

template <typename T>
struct Foo {};

using SomeType = Foo<Bar>;

template <typename T>
using Template = decltype(get_template<T>(SomeType{}));

int main() {
    static_assert(std::is_same<Foo<Baz>, Template<Baz>>::value, "");
}

(SomeType Template, ), , .

+1

All Articles