Шаблон Шаблон C ++ Функция - PullRequest
       5

Шаблон Шаблон C ++ Функция

5 голосов
/ 26 сентября 2011

Как мне написать шаблонную функцию, которая работает с произвольным контейнером произвольного типа? Например, как мне обобщить эту фиктивную функцию

template <typename Element>
void print_size(const std::vector<Element> & a)
{
    cout << a.size() << endl;
}

до

template <template<typename> class Container, typename Element>
void print_size(const Container<Element> & a)
{
    cout << a.size() << endl;
}

Вот типичное использование

std::vector<std::string> f;
print_size(f)

Это дает ошибку

tests/t_distances.cpp:110:12: error: no matching function for call to ‘print(std::vector<std::basic_string<char> >&)’. I'm guessing I must tell the compiler something more specific about what types that are allowed.

Как называется вариант использования шаблона и как мне это исправить?

Ответы [ 5 ]

13 голосов
/ 26 сентября 2011

Есть ли конкретная причина для вас использовать шаблон шаблона? Почему не просто так?

template <typename Container>
void print_size(Container const& a)
{
    cout << a.size() << endl;
}

В общем, шаблоны шаблонов не стоят проблем. В вашем конкретном случае они, безусловно, бесполезны, и если вам действительно нужен доступ к типу члена, я предлагаю вам поклониться обычной практике и использовать метафункцию (typename Container::value_type в данном случае).

3 голосов
/ 07 апреля 2015

Я знаю, что вопрос задавался давным-давно, но у меня была та же проблема, и решение состоит в том, что вам нужно написать

template <template <typename,typename> class Container, typename element, typename Allocator>
void print_size(Container<element, Allocator> & a)
{
    std::cout << a.size() << std::endl;
}

потому что вектор имеет два параметра шаблона

3 голосов
/ 26 сентября 2011

Проблема в том, что шаблон vector принимает два аргумента типа, а ваш шаблон принимает только аргументы шаблона, которые принимают один аргумент.Самое простое решение - немного повысить безопасность типов и просто использовать Container в качестве типа:

template <typename Container>
void print_size( Container const & c ) {
   std::cout << c.size() << std::endl;
}

Возможно добавление статических проверок (независимо от типа Container он должен иметь value_typeвложенный тип Element ...) Альтернативой может быть приведение аргумента шаблона шаблона в соответствие шаблонам, которые необходимо передать (включая распределитель для последовательностей, распределитель и предикат порядка для ассоциативных контейнеров) ...

2 голосов
/ 26 сентября 2011

Зачем когда-либо использовать что-то вроде

template <template<typename> class Container, typename Element>
void print_size(const Container<Element> & a)
{
    cout << a.size() << endl;
}

? Используйте это более простым способом:

template<typename Container>
void print_size(const Container & a)
{
    cout << a.size() << endl;
}

При звонке print_size(f) вы будете звонить print_size с Container, равным vector<string>.

0 голосов
/ 26 сентября 2011

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

template <typename IteratorType>
void print_size(IteratorType begin, IteratorType end) {
   std::cout << std::distance(begin, end) << std::endl;
}

Для вызова:

std::vector<std::string> f;
print_size(f.begin(), f.end());
...