变量类型定义或“Bimaps完成C ++ 0x方式”
简短的问题:我可以键入一个可变参数包吗? 我需要template <typename ...T> struct Forward { typedef T... args; };
template <typename ...T> struct Forward { typedef T... args; };
。
长版本:
我正在考虑在C ++ 0x中重新实现卓越的boost bimap。 回想一下, S
和T
两种类型的bimap是S x
和T y
之间std::set
关系的std::set
。 这些对象本身存储在两个独立的内部容器中,并且这些关系跟踪我想要的关联迭代器; 这两种类型都可以通过“左”和“右”查找作为键。 取决于内部容器的选择,值可能是唯一的或者不是,例如,如果左边的容器是一个集合,并且正确的容器是多层集合,那么一个x
可以映射到许多不同的y
,右边的查找会给出一个等值范围。 流行的内部容器set
, multiset
, vector
和list
,也可能是unordered_*
版本。
所以我们需要一个接受两个容器作为模板参数的类型:
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
的指定行中,我无法弄清楚如何输入参数包! (注释行给出编译器错误。)
[我想我可以去一个懒惰的版本Bimap<std::set<int, MyPred>, std::multiset<char, YourPred>> x;
并通过LeftCont::value_type
和RightCont::value_type
提取类型,但我认为它会更好,如果我可以使关键字类型为我的主模板参数并允许默认为std::set
容器。]
您可以通过将可变参数包封装在一个元组中,然后使用以下两个辅助模板结构来转发实际的可变参数来实现您想要的功能:
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下编译得很好
您可以键入一个元组。 但是,我不知道如何将这些类型再次取出。
最简单的事情就是接受两种完整的类型。
链接地址: http://www.djcxy.com/p/37153.html上一篇: Variadic typedefs, or "Bimaps done the C++0x way"
下一篇: print std::tuple