Шаблоны функций C ++ с шаблонными аргументами - PullRequest
2 голосов
/ 21 августа 2011

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

#include<iostream>
#include<list>
#include<vector>

template<class data_type, template<class> class container_type>
void type(container_type<data_type>& _container){
        std::cout<<typeid(container_type).name()<<std::endl;
}


int main(){

    std::list<int> list_t;
    std::vector<int> vector_t;
    type(list_t);
    type(vector_t);
}

Тип container_type, находящийся внутри этой функции, всегда равен _Container_base_aux_alloc_empty, который (я думаю) является базовым классом стандартных контейнеров.

Что здесь происходит?

Как бы заставить эту функцию возвращать правильный тип?

Ответы [ 4 ]

2 голосов
/ 21 августа 2011

Идентификатор типа container_type бесполезен, потому что это просто класс шаблона, а класс шаблона вообще не является реальным типом, он становится единичным после создания экземпляра. Так что вам действительно нужен тип data_type для типа значения и тип container_type<data_type> для типа экземпляра контейнера. Еще лучше, конечно, принять container_type<data_type>::value_type в качестве типа значения.

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

template <template <typename...> class Container, typename ...Args>
void print_type(const Container<Args...> &)
{
  typedef typename Container<Args...>::value_type value_type;
  print(typeid(Container<Args...>).name());
  print(typeid(value_type).name());
}
1 голос
/ 21 августа 2011

У вас уже есть тип контейнера.Это data_type.Просто используйте это так.Если вы сомневаетесь, вы также можете использовать typename container_type::value_type, который является typedef для аргумента шаблона контейнера.

Так много для с использованием типов.Возвращение типа - это нечто совершенно другое в C ++ и обычно считается частью метапрограммирования шаблонов.

Этот довольно бессмысленный фрагмент извлекает value_type из некоторого типа T.

template<typename T>
struct inner_type {
  typedef T::value_type value_type;
};

Но вы могли бы также использовать value_type напрямую и избежать этого обфускации.

1 голос
/ 21 августа 2011

Ваш код не будет работать, потому что, как только кто-то поменяет распределитель или что-то в этом роде, все готово. Вы должны взять любой T и использовать ::value_type, если в C ++ 03, или тип удержания в C ++ 0x.

Кроме того, .name() вообще не определено, чтобы возвращать что-либо полезное. В любой ситуации. Реализация может возвращать «har har sucker! Удачи, используя эту языковую особенность» для каждого типа и быть соответствующей.

1 голос
/ 21 августа 2011

Я бы не очень доверял выводу typeid (). type_info :: Name не гарантирует возврата уникального идентификатора. Так что вполне возможно, что тип внутри функции - это то, что вы ожидаете.

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

template<class data_type, template<class> class container_type>
void type_helper(container_type<data_type>& _container, const char* charStr){
        std::cout<< charStr << std::endl
}

#define type(container) type_helper(container, #container)
...