Контейнер STD внутри метода шаблона - PullRequest
6 голосов
/ 27 февраля 2011

Привет.

Я не очень хорошо знаю, как объяснить себя, но я верю, что фрагмент кода поможет вам понять, что я собираюсь сделать:

template<class A, class B>
void myFunction(A<B>& list)
{
  typename A<B>::iterator current = list.begin();
  typename A<B>::iterator end = list.end();

  while (current != end)
  {
    current++;
  }
}

Где A - контейнер STL (вектор, список ...).Это похоже на начало, но с шаблонами: шаблон, внутри шаблона и т. Д ...

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

Это, конечно, не компилируется (он говорит: «А не шаблон»).

Кто-нибудь знает, как создать такой шаблон

Ответы [ 3 ]

7 голосов
/ 27 февраля 2011

Вы ищете шаблон шаблона параметра

template<template<class T, class All = std::allocator<T> > class A, class B>
void myFunction(A<B>& list)
{
  typename A<B>::iterator current = list.begin();
  typename A<B>::iterator end = list.end();

  while (current != end)
  {
    current++;
  }
}

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

template<class C>
void myFunction(C& list)
{
   ...
}

используйте вот так

vector<char> v;
myFunction(v);

Ваш оригинальный код должен называться так:

myFunction<std::vector, char> (v)

, который намного более многословен и не имеет особой пользы

2 голосов
/ 27 февраля 2011

A и B будут конкретными типами (а не шаблонами), поэтому A<B> не имеет смысла.

Вы можете написать свой код следующим образом:

template<class List>
void myFunction(List &list)
{
  typename List::iterator current = list.begin();
  typename List::iterator end = list.end();

  while (current != end)
  {
    current++;
  }
}

Если вам нужно знать, какой тип элемента в этом списке, для этого в списке есть определение типа:

typename List::value_type
0 голосов
/ 27 февраля 2011

Ну, чтобы решить эту небольшую примерную проблему.Это довольно просто.vector<int> - это класс, поэтому вам не нужно объявлять A<B> в прототипе.Вы можете просто сделать это:

template<class A>
void myFunction(A& list)
{
  typedef typename A::value_type B; //do this if you need to know the type of the elements.
  typename A::iterator current = list.begin();
  typename A::iterator end = list.end();

  while (current != end)
  {
    current++;
  }
}

Но если вам действительно нужно, вы также можете объявить аргумент шаблона как шаблон:

template< template<class> class A, class B >
void myFunction(A<B>& list)
{
  typename A<B>::iterator current = list.begin();
  typename A<B>::iterator end = list.end();

  while (current != end)
  {
    current++;
  }
}

Но вышеприведенное не очень рекомендуетсяи большинство шаблонов классов имеют набор вложенных typedef (например, iterator и value_type в контейнерах STL), так что вы можете получить всю необходимую информацию о типе, не используя эти параметры шаблона шаблона.Таким образом, первый способ обычно является предпочтительным и более обычным способом (обычно также меньше проблем с его выполнением, т. Е. Компилятор склонен «не любить» параметры шаблона).

Кроме того,Вы не можете использовать контейнеры STL очень легко с параметрами шаблона шаблона, потому что все контейнеры STL имеют эти «скрытые» аргументы шаблона (например, «allocator» и «Compare» для отсортированных контейнеров).Таким образом, вам придется перечислить все это, в противном случае компилятор не сможет сделать совпадение.Кроме того, у вас не будет очень «универсальной» функции, потому что вам придется так много полагать о прошедшем контейнере STL, что он будет обслуживать только один или два типа контейнеров.Действительно лучше использовать первый способ.

...