2012-07-13 33 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

相關問題