在几种可能性中提升变体

时间:2016-03-10 15:01:05

标签: c++ template-meta-programming boost-variant

假设我有一个大小为一种类型的模板类:

String

我想生成一个template<size_t N, typename T> class C {}; ,它能够将这个类保存在多种大小和类型上,例如对于尺寸boost::variant1以及类型2int,它将是

unsigned int

问题在于我需要在多个地方进行此设置,并且每次都需要不同的尺寸和类型。 是否有一些模板元编程魔法可以从可能值列表中生成这些变体,这些都是

typedef boost::variant<
    C<1, int>, 
    C<1, unsigned int>, 
    C<2, int>, 
    C<2, unsigned int>
> my_variant;

1 个答案:

答案 0 :(得分:4)

好的,我做到了。方法如下:

#include <boost/variant.hpp>
#include <tuple>
#include <iostream>
#include <typeinfo>

template<size_t N, typename T>
class C
{};

template<template <size_t, class> class T>
struct combine
{
    template<size_t... Ns> struct sizes;

    template<size_t N>
    struct sizes<N>
    {
        template<typename... Types>
        struct types
        {
            typedef std::tuple<T<N, Types>...> type;
        };
    };

    template<size_t N, size_t... Ns>
    struct sizes<N, Ns...>
    {
        template<typename... Types>
        struct types
        {
            typedef typename sizes<N>::template types<Types...>::type head;
            typedef typename sizes<Ns...>::template types<Types...>::type tail;
            typedef decltype(std::tuple_cat<head, tail>(std::declval<head>(), std::declval<tail>())) type;
        };
    };
};

template<typename... Types>
auto to_variant(const std::tuple<Types...>&)
{
    return boost::variant<Types...>();
}

struct typename_visitor : public boost::static_visitor<>
{
    template<size_t N, typename T>
    void operator()(const C<N, T>& c)
    {
        std::cout << "C<" << N << ", " << typeid(T).name() << ">\n";
    }
};

int main()
{
    combine<C>::sizes<1, 2>::types<int, unsigned int>::type v;
    auto var = to_variant(v);
    var = C<1, int>();
    // var = C<3, int>(); // doesn't compile
    // var = C<1, short>(); // doesn't compile
    var.apply_visitor(typename_visitor()); // prints C<1, int>
}