Помогите с шаблонами шаблонов c ++ - PullRequest
2 голосов
/ 11 июня 2009

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

{(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);
}

Нет шаблонов typedefs, поэтому я создал класс свойств для хранения типа, который выходной итератор от:

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'

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

Ответы [ 2 ]

8 голосов
/ 11 июня 2009

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

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

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

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

Отредактировано: Вырежьте несколько советов, неправильно прочитали ваш код.

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

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 голосов
/ 11 июня 2009
Шаблон

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...