8

短い質問: 可変引数パックを型定義できますか? が必要template <typename ...T> struct Forward { typedef T... args; };です。


長いバージョン:

C++0x で優れたブースト バイマップを再実装することを考えていました。2 つのタイプの bimapSTがとの間std::set関係であることを思い出してください。オブジェクト自体は 2 つの独立した内部コンテナーに格納され、リレーションは関連付けられた反復子を追跡します。どちらのタイプも、「左」および「右」ルックアップを介してキーとして機能できます。内部コンテナの選択に応じて、値が一意である場合とそうでない場合があります。たとえば、左のコンテナがセットで右のコンテナがマルチセットの場合、多くの異なる にマップでき、右のルックアップで等しい範囲が得られます。人気のある内部コンテナは、、およびであり、おそらくS xT yxysetmultisetvectorlistunordered_*バージョンも。

したがって、テンプレート パラメーターとして 2 つのコンテナーを受け入れる型が必要です。

class Bimap<S, T, std::set, std::multiset>

しかし、コンテナは任意の数の引数を取ることができることを受け入れる必要があるため、それらもすべて渡す必要があります。可変引数のセットが1 つだけ必要な場合は、それらを直接渡すことができるため、問題にはなりません。しかし、ここでは2組の引数が必要なので、次のように使用するフォワーダーを書きたいと思います。

Bimap<int, int, std::set, std::set, Forward<std::less<int>, MyAllocator>, Forward<std::greater<int>, YourAllocator>> x;

私が思いついたテンプレートは次のとおりです。

#include <set>
#include <cstdint>

template <typename ...Args>
struct Forward
{
  typedef Args... args; // Problem here!!
  static const std::size_t size = sizeof...(Args);
};

template <typename S, typename T,
          template <typename ...SArgs> class SCont,
          template <typename ...TArgs> class TCont,
          typename SForward = Forward<>, typename TForward = Forward<>>
class Bimap
{
  typedef SCont<S, typename SForward::args> left_type;
  typedef TCont<T, typename TForward::args> right_type;

  template <typename LeftIt, typename RightIt> struct Relation; // to be implemented

  typedef Relation<typename left_type::const_iterator, typename right_type::const_iterator> relation_type;

};


int main()
{
  Bimap<int, int, std::set, std::set, Forward<std::less<int>>, Forward<std::greater<int>>> x;
}

残念ながら、指定された行ではForward、パラメーター パックを typedef する方法がわかりません! (コメント行でコンパイラ エラーが発生します。)

[怠惰なバージョンを使用してandBimap<std::set<int, MyPred>, std::multiset<char, YourPred>> x;を介して型を抽出することもできると思いますが、キーの型を主要なテンプレート引数にして、コンテナーへのデフォルト設定を許可できればもっといいと思いました。]LeftCont::value_typeRightCont::value_typestd::set

4

2 に答える 2

9

可変引数パックをタプルにカプセル化し、後で次の 2 つのヘルパー テンプレート構造体を使用して実際の可変引数を転送することで、目的を達成できます。

template<typename PackR, typename PackL>
struct cat;

template<typename ...R, typename ...L>
struct cat<std::tuple<R...>, std::tuple<L...>>
{
        typedef std::tuple<R..., L...> type;
};

template<typename Pack, template<typename ...T> class Receiver>
struct Unpack;

template<typename ...Args, template<typename ...T> class Receiver>
struct Unpack<std::tuple<Args...>, Receiver>
{
        typedef Receiver<Args...> type;
};

コードサンプルは次のようになります。

#include <set>
#include <cstdint>
#include <tuple>

template<typename PackR, typename PackL>
struct Cat;

template<typename ...R, typename ...L>
struct Cat<std::tuple<R...>, std::tuple<L...>>
{
        typedef std::tuple<R..., L...> type;
};

template<typename Pack, template<typename ...T> class Receiver>
struct Unpack;

template<typename ...Args, template<typename ...T> class Receiver>
struct Unpack<std::tuple<Args...>, Receiver>
{
        typedef Receiver<Args...> type;
};

template<typename ...Args>
struct Forward
{    
        //typedef Args... args; // Problem here!!
        typedef std::tuple<Args...> args; // Workaround

        static const std::size_t size = sizeof...(Args);
};

template<typename S, typename T, 
        template<typename ...SArgs> class SCont, 
        template<typename ...TArgs> class TCont, 
        typename SForward = Forward<> ,
        typename TForward = Forward<>>
class Bimap
{
        //typedef SCont<S, typename SForward::args> left_type;
        //typedef TCont<T, typename TForward::args> right_type;
        typedef typename Unpack<typename Cat<std::tuple<S>, typename SForward::args>::type, SCont>::type left_type; //Workaround
        typedef typename Unpack<typename Cat<std::tuple<T>, typename TForward::args>::type, TCont>::type right_type; //Workaround

        template<typename LeftIt, typename RightIt> struct Relation; // to be implemented

        typedef Relation<typename left_type::const_iterator, typename right_type::const_iterator> relation_type;

};

int main()
{
    Bimap<int, int, std::set, std::set, Forward<std::less<int>> , Forward<std::greater<int>>> x;
}

gcc 4.6.0で問題なくコンパイルされます

于 2011-06-16T15:48:12.050 に答える
0

タプルを型定義できます。ただし、型を再び取得する方法はわかりません。

最も簡単な方法は、2 つの完全な型を受け入れることです。

于 2011-06-16T11:15:38.507 に答える