2012-07-13 30 views
6

我愿做这样的事情:如何从变种型包装中获得特定类型?

template<typename ...T> struct foo 
{ 
    bar<0 /*to index through types in pack*/ ,T...>::type var1; 
    bar<1 /*to index through types in pack*/ ,T...>::type var2; 
    ... 
} 

但我如何定义bar?没有递归技术想到做到这一点。

我想要一种通用技术,以便我可以从类型包中键入任何特定类型,而不仅仅是示例中显示的两种。

+0

你想VAR1和VAR2什么地方,如果...的sizeof(T)== 0或...的sizeof(T)== 1 ? – Andrzej 2012-07-13 12:08:34

+3

为什么不使用'std :: tuple '?以'std :: get (tup)'和类型为'std :: tuple_element > :: type'访问元素。 – Xeo 2012-07-13 12:38:09

+0

@Xeo你是对的,但我想学习使用var模板的基本技巧。我希望你能理解。 – M3taSpl0it 2012-07-13 12:47:13

回答

5
#include <iostream> 
#include <typeinfo> 

template<class T, class T2, class... Args> 
class C 
{ 
public: 
    typedef T type1; 
    typedef T2 type2; 
}; 

int main() 
{ 
    typedef C<int, double, int, float> c; 
    std::cout << typeid(c::type1).name() << " " << typeid(c::type2).name() << std::endl; 
} 

或mb这样的事情。

#include <iostream> 
#include <typeinfo> 

template<int N, class T, class... Args> 
struct expand 
{ 
public: 
    typedef typename expand<N - 1, Args...>::type type; 
}; 

template<class T, class... Args> 
struct expand<1, T, Args...> 
{ 
public: 
    typedef T type; 
}; 

template<class... Args> 
class argsExpander 
{ 
public: 
    typedef typename expand<1, Args...>::type type1; 
    typedef typename expand<2, Args...>::type type2; 
}; 

template<class... Args> 
class C 
{ 
public: 
    typename argsExpander<Args...>::type1 var1; 
    typename argsExpander<Args...>::type2 var2; 
}; 

int main() 
{ 
    C<int, double, int, float> c; 
    std::cout << typeid(c.var1).name() << " " << typeid(c.var2).name() << std::endl; 
} 

http://liveworkspace.org/code/7de289f128e86eb6006f576cbaf98991

+0

我认为这个问题意味着'typedef'部分应该自动发生 – 2012-07-13 12:06:37

+2

'expand'成语非常聪明。 – tenfour 2012-07-13 12:09:31

+0

@refp代码已更新。 – ForEveR 2012-07-13 12:14:17

1

是的,你可以用递归你这样做......其实更多或更少的重新实施std::tuple(和含蓄std::get)。

努力工作来进入成员,因为你不能称之为var1,var2等,除非你手动命名它们。

template <typename... TypeList> struct foo; 

template <typename Head, typename... Tail> 
struct foo<Head, Tail...>: public foo<Tail...> 
{ 
    Head var; 
}; 

我在这里用继承,但组成(使用foo<Tail...> tail成员)的作品也是如此。

现在,如果你的类型是独一无二的,你可以访问类型的成员...

// this overload if VarType is the first 
template <typename VarType, typename... FooTail> 
VarType& foo_get(foo<VarType, FooTail...>& f) 
{ 
    return f.var; 
} 

// this overload to walk down to foo's parent 
template <typename VarType, typename FooHead, typename... FooTail> 
VarType& foo_get(foo<FooHead, FooTail...>& foo) 
{ 
    return foo_get<VarType>(static_cast<foo<FooTail...>>(f)); 
} 

// call like: 
// int &x = foo_get<int>(my_foo_object); 

,或者您可以通过访问位置:

template <int N, typename... TypeList> struct GetHelper; 

template <typename Head, typename... Tail> 
struct GetHelper<0, Head, Tail...> 
{ 
    static Head& get(foo<Head, Tail...> &f) { return f.var; } 
}; 

template <int N, typename Head, typename... Tail> 
struct GetHelper<N, Head, Tail...>: public GetHelper<N-1, Tail...> 
{}; 

template <int N, typename... TypeList> 
auto foo_get(foo<TypeList...> &f) 
    -> GetHelper<N, TypeList...>::get(*static_cast<foo<TypeList...>*>(0)) 
{ 
    return GetHelper<N, TypeList...>::get(f) 
} 

// call like: 
// int &x = foo_get<2>(my_foo_object); 

这些都可以提高到得到更好的错误报告(虽然我已经使用了这两种技术,但我甚至没有试过编译这个示例代码)

+2

而不是重新实现'std :: tuple',OP应该简单地使用它。 – Xeo 2012-07-13 12:40:50

+0

我同意,但由于OP喜欢这个看起来不符合问题的解决方案,所以我不确定我是否理解了这个问题。 – Useless 2012-07-13 13:01:56

1

如果我正确理解你的问题,你想实现类似的东西Ø的std ::元组:

我认为元组这种方式来实现:

template <class T> 
class tuple 
{ 
    T mem; 
}; 

template <class T, class... REST> 
class tuple : tuple<REST...> 
{ 
    T mem; 
}; 
1

只需使用的std ::元组作为@Xeo不断评论。这很方便,而且完全符合你所要做的。

报价:

为什么不直接使用std::tuple<T...>

访问元素std::get<I>(tup)

类型为std::tuple_element<I, std::tuple<T...>>::type

相关问题