2016-03-10 1 views
4

Скажем, у меня есть класс шаблона более одного размера на один тип:подталкивание вариант через несколько возможностей

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

Я хочу, чтобы создать boost::variant, который способен удерживать этот класс в течение нескольких типов и размеров, например, для размеров 1 и 2 и типов int и unsigned int будет

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

Проблема заключается в том, что мне нужен этот параметр в нескольких местах, и каждый раз с разных размеров и типов. Есть ли какое-нибудь шаблон метапрограммирование магии, чтобы генерировать эти варианты из списка возможных значений, то вдоль линий

typedef generate_variant<C, 1, 2, int, unsigned int>::type my_variant; 
+0

Я думаю, что это возможно с вариационными шаблонами. – zapredelom

+0

Нет. Вы не сможете предоставить пакет параметров шаблона, который может быть как интегральным, так и типом. – SergeyA

+0

возможно, используя std :: integral_constant? –

ответ

2

ОК, я сделал это. Вот так:

#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> 
} 
Смежные вопросы