[英]Retrieve the template a type is instantiated from
How can I retrieve the template a type was originally instantiated from? 如何检索最初实例化类型的模板?
I'd 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 I can achieve this through partial specialization, but this forces me to specialize get_template
for every template I want to use it with: 我知道我可以通过部分特化来实现这一点,但是这迫使我为每个我想要使用它的模板专门化
get_template
:
template <typename T>
struct get_template;
template <typename T>
struct get_template<Foo<T>>
{
template <typename X>
using type = Foo<X>;
};
Is there a way around this limitation? 有没有解决这个限制的方法?
You could do something like that, using a template template parameter (should work for templates with any number of type arguments): 您可以使用模板模板参数执行类似的操作(适用于具有任意数量类型参数的模板):
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>;
As mentioned by @Yakk in the comment, the above only works for template that only have type arguments. 正如@Yakk在评论中所提到的,上面只适用于只有类型参数的模板。 You can specialize for template with specific pattern of type and non-type arguments, eg:
您可以专门使用具有特定模式类型和非类型参数的模板,例如:
// 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...>;
};
...but you will not be able to specialize it for arbitrary templates. ...但您无法将其专门用于任意模板。
DEMO (with Foo
and std::pair
): 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, "");
Not sure I got the question. 不确定我有问题。 Would this work?
这会有用吗?
#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, "");
}
You can generalize even more ( SomeType
could be a template parameter of Template
, as an example), but it gives an idea of what the way is. 您可以进一步概括(
SomeType
可以是Template
的模板参数,作为示例),但它可以了解方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.