8

简短的问题:我可以键入定义可变参数包吗?我需要template <typename ...T> struct Forward { typedef T... args; };


长版:

我正在考虑在 C++0x 中重新实现出色的boost bimap 。回想一下,两种类型的 bimapST是和之间std::set关系。对象本身存储在两个独立的内部容器中,我想这些关系跟踪关联的迭代器;这两种类型都可以通过“左”和“右”查找作为键。根据内部容器的选择,值可能是唯一的,也可能不是唯一的,例如,如果左容器是一个集合,而右容器是一个多重集合,那么可以映射到许多不同的 s,而右查找给出一个相等的范围。流行的内部容器是、和,也许还有S xT yxysetmultisetvectorlistunordered_*版本也是。

所以我们需要一个接受两个容器作为模板参数的类型:

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

但我们必须接受容器可以接受任意多个参数,因此我们也需要传递所有这些参数。如果我们只需要组可变参数,那不是问题,因为我们可以直接传递它们。但是现在我们需要两组参数,所以我想写一个转发器,像这样使用:

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

您可以通过将可变参数包封装在一个元组中来实现您想要的,然后使用以下两个帮助模板结构来转发实际的可变参数:

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

你可以 typedef 一个元组。但是,我不知道如何让这些类型再次出现。

最简单的做法是只接受两种完整类型。

于 2011-06-16T11:15:38.507 回答