我对模板有疑问,它在代码中:
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)
};
答案 0 :(得分:5)
这是一个通用的模板参数类型提取器:
#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;
答案 1 :(得分:1)
如果我正确理解了您的问题,您可以使用模板专业化,如下所示。鉴于您的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, "!");
}
以下是相应的live example。
答案 2 :(得分:1)
如果您不想或不能将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标准库中的东西:)顺便说一句,这感觉就像是应该已经以更通用的解决方案形式提供的东西......