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か? これを行うための再帰手法は思い浮かびません。

例に示されている 2 つだけでなく、型パックから特定の型を型定義できるように、一般的な手法が必要です。

4

4 に答える 4

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

于 2012-07-13T12:04:45.113 に答える
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);

これらの両方を改善して、エラー報告を改善することができます (私は両方の手法を使用しましたが、このサンプル コードをコンパイルすることさえ試みていません)。

于 2012-07-13T12:23:45.960 に答える
1

@Xeo がコメントし続けるので、単純に std::tuple を使用します。それは便利で、あなたがやろうとしていることを正確に行います。

見積もり:

を使用しないのはなぜstd::tuple<T...>ですか?

std::get<I>(tup)およびとして要素にアクセスする

タイプstd::tuple_element<I, std::tuple<T...>>::type

于 2012-07-13T13:25:28.070 に答える
1

あなたの質問を正しく理解できれば、std::tuple に似たものを実装する必要があります。

タプルは次のように実装されていると思います:

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

template <class T, class... REST>
class tuple : tuple<REST...>
{
  T mem;
};
于 2012-07-13T12:36:06.737 に答える