我有一个关于模板的问题,它在代码中:
template<typename T>
struct foo {
T t;
};
template<typename FooType>
struct bar {
T t; //<- how to get T here (preferably without using typedef in foo)
};
这是一个通用模板参数类型提取器:
#include <tuple>
template <typename> struct tuplify;
template <template <typename...> class Tpl, typename ...Args>
struct tuplify<Tpl<Args...>>
{
using type = std::tuple<Args...>;
};
template <typename T, unsigned int N>
using get_template_argument
= typename std::tuple_element<N, typename tuplify<T>::type>::type;
用法:
get_template_argument<std::vector<int>, 1> a; // is a std::allocator<int>
或者在你的情况下:
get_template_argument<FooType, 0> t;
如果我正确理解了您的问题,您可以按如下方式使用模板专业化。给定您的foo<>
课程模板:
template<typename T>
struct foo {
T t;
};
以这种方式定义bar<>
主模板和相应的特化:
template<typename FooType>
struct bar;
template<typename T>
struct bar<foo<T>> {
T t; // T will be int if the template argument is foo<int>
};
假设您总是应该bar
通过提供一个实例foo<>
作为类型参数来实例化,您可以不定义主模板。
特化将匹配foo<T>
模式,从而为您提供在foo<>
中实例化的类型T
。
以下是如何使用一个简单的程序来测试这种方法的有效性:
#include <type_traits>
int main()
{
bar<foo<int>> b;
// This will not fire, proving T was correctly deduced to be int
static_assert(std::is_same<decltype(b.t), int>::value, "!");
}
这是相应的现场示例。
如果您不想或不能添加 typedef 到foo
,您可以另外编写一个独立的“提取器”模板
template <typename T> struct ExtractT;
template <typename T> struct ExtractT<foo<T> > {
typedef T type;
};
并将其用作
template<typename FooType>
struct bar {
typename ExtractT<FooType>::type t;
};
您可以ExtractT
更进一步,将其与foo
template <typename T> struct ExtractT;
template <template <typename> class C, typename T> struct ExtractT<C<T> > {
typedef T type;
};
依此类推,直到您从 Boost 或 C++11 标准库中重新发明一些东西:) 顺便说一句,这感觉就像应该已经以更通用的解决方案的形式提供的东西......