variadic typedefs、または「bimapsがC ++ 0xウェイを行った」
質問
短い質問:バリアード引数パックを入力できますか?私は欲しい template <typename ...T> struct Forward { typedef T... args; };
.
ロングバージョン:
私は素晴らしいものを再実装することを考えていました BIMAPをブーストします C ++ 0x。 2つのタイプのbimapを思い出してください S
と T
aです std::set
の 関係 の間に S x
と T y
. 。オブジェクト自体は2つの独立した内部容器に保存され、関係は関連する反復因子を追跡します。どちらのタイプも、「左」と「右」のルックアップを介してキーとして機能します。内部コンテナの選択に応じて、値は一意であるかどうか、たとえば、左のコンテナがセットであり、適切なコンテナがマルチセットである場合、次に1つは x
多くの異なるものにマッピングできます y
s、および右のルックアップは等しい範囲を与えます。人気のある内部コンテナはそうです set
, multiset
, vector
と list
, 、そして多分 unordered_*
バージョンも。
したがって、2つのコンテナをテンプレートパラメーターとして受け入れるタイプが必要です。
class Bimap<S, T, std::set, std::multiset>
しかし、コンテナがarbitrary意的な多くの議論を受け取ることができることを受け入れなければならないので、それらすべてを渡す必要があります。必要な場合 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
パラメーターパックを入力する方法を理解できません! (コメントされた行には、コンパイラエラーが発生します。)
私は怠zyなバージョンに行くことができると思います Bimap<std::set<int, MyPred>, std::multiset<char, YourPred>> x;
経由でタイプを抽出します LeftCont::value_type
と RightCont::value_type
, 、しかし、キータイプを私の主要なテンプレートの引数を作成し、デフォルトを許可することができればもっといいと思いました std::set
コンテナ。
解決
あなたは、タプルでバリアード引数パックをカプセル化し、後に次の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の下で正常にコンパイルされます
他のヒント
タプルを入力できます。しかし、私はどのようにタイプを再び取り戻す方法を知りません。
最も簡単なことは、2つの完全なタイプを受け入れることです。