2009-06-11 3 views
2

Итак, я написал stl-подобный алгоритм под названием cartesian_product. Для тех, кто не знает, декартовым продуктом являются всевозможные пары элементов из двух наборов. Так декартово произведение {1, 2, 3} и {10, 20, 30} являетсяПомощь с шаблонами шаблонов C++

{(1,10), (1,20), (1,30), (2,10), (2,20), (2,30), (3,10), (3,20), (3,30)}

Так функция выглядит

template <typename InIt1, typename InIt2, typename OutIt> 
void 
cartesian_product(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt out) 
{ 
    for (; first1 != last1; ++first1) 
     for (InIt2 it = first2; it != last2; ++it) 
      *out++ = std::make_pair(*first1, *it); 
} 

Там не шаблонные определения типов, так что я сделал класс черты держать тип, который в Выходной итератор от:

template <typename ObjA, typename ObjB, template <typename> class Container> 
struct cartesian_product_traits 
{ 
    typedef Container<std::pair<ObjA, ObjB> > type; 
}; 

Итак, я могу сказать:

typedef cartesian_product_traits<int, int, std::vector>::type IntPairList; 
IntPairList my_list; 
cartesian_product(v1.begin(), v1.end(), 
        v2.begin(), v2.end(), 
        std::back_inserter(my_list); 

но это, похоже, не компилируется. Я получаю хорошую ошибку:

error C3201: the template parameter list for class template 'std::vector' does not match the template parameter list for template parameter 'Container' 

Так что я в тупике. Как мне заставить это работать?

ответ

8

Список параметров шаблона для вектора не только один элемент, он занимает два:

template < class T, class Allocator = allocator<T> > class vector 

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

template <typename ObjA, typename ObjB, template <typename, typename> class Container> 
struct cartesian_product_traits 

Отредактировано: Порекомендовано, неправильно читайте код.

Способ сделать это правильно было бы использовать VARIADIC макрос на шаблонного параметра шаблона:

template <typename ObjA, typename ObjB, template <typename ...> class Container> 
struct cartesian_product_traits 

Но это далеко от того, чтобы быть стандартным. Если бы это был мой код, я бы, наверное, просто потребители колотить полного шаблона:

std::vector< std::pair<int, int> > 

короче

cartesian_product_traits<int, int, vector> 

и последний будет только помочь, если определение декартова произведения изменилось.

2

std::vector10 Шаблон на самом деле довольно сложный (с дополнительными параметрами шаблона для распределителей & c) - и другие контейнеры в stdlib также не проще. В вашей обуви я бы сделал третий параметр cartesian_product_traits в простой typename PairsContainer и в зависимости от вызывающего, чтобы перейти к небольшой проблеме передачи его в качестве подходящего контейнера с парами.

+0

+1 голос за то, что он сказал «& c» для «и т. Д.». – rlbond

+2

-1 голос, чтобы отозвать, что upvote от @rlbond –

Смежные вопросы