Вывод сложного типа из параметра шаблона функции - PullRequest
1 голос
/ 01 сентября 2011

У меня есть другой вопрос шаблона C ++. Я ленивый парень, поэтому стараюсь не указывать аргументы шаблона, если это возможно. Теперь у меня есть функция

template< typename EasyLookingObject >
void myfunct( EasyLookingObject& obj ) {
  //do something with obj
}

Теперь EasyLookingObject на самом деле

boost::ptr_list< A< STDContainer::<TargetType*> > >

Чтобы работать с obj, мне нужно знать типы STDContainer и TargetType. Можете ли вы помочь мне получить эти типы?

Проблема 1: EasyLookingObject :: value_type действительно дает мне тип указателя. Как мне вывести полный тип из него и использовать его внутри typedef?

То же самое, вероятно, относится к проблеме STDContainer :: value_type.

Ответы [ 3 ]

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

Удаление указателя тривиально с использованием частичной специализации:

template <typename T>
struct remove_ptr {
    typedef T type;
};

template <typename T>
struct remove_ptr<T*> : remove_ptr<T> { };

(я уверен, что Boost также имеет что-то вроде этого.)

Собираем все вместе:

typedef typename remove_ptr<typename EasyLookingObject::value_type>::type a_t;
typedef typename a_t::container_type container_t;
typedef typename remove_ptr<typename container_t::value_type>::type target_t;
0 голосов
/ 01 сентября 2011

Проблема 1: EasyLookingObject :: value_type действительно дает мне тип указателя. Как мне вывести полный тип из него и использовать его внутри typedef?

Возможно, вам не нужно извлекать typedefs.

Просто передайте каждый извлеченный элемент другой перегруженной функции. Используйте функцию извлечения, похожую на boost::get_pointer(), чтобы извлечь указатель из ссылки или простой или умный указатель.

template<class Container>
void do_something_item(Item* item); // overload for different types as necessary

template<class Container>
void do_something(Container& c) {
    for(typename Container::iterator i(c.begin()), j(c.end()); i != j; ++i) {
        using boost::get_pointer; 
        do_something_item(get_pointer(*i)); // use ADL to find get_pointer() overload
    }
}
0 голосов
/ 01 сентября 2011

Если вы действительно не можете вывести правильные типы из класса typedefs (в чем я сомневаюсь, дважды проверьте документацию), вы можете указать параметры шаблона немного более явно:

template <template <typename...> class Container, typename T, typename ...Args>
void myfunc(const Container<T*, Args...> & c)
{
  // ...
}

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

template <template <typename A, typename = std::allocator<A> > class Container,
          typename T>
void myfunc(const Container<T*> & c);

Это будет соответствовать только Container<T*, std::allocator<T*>>. Вот общая версия для двухпараметрических контейнеров:

template <template <typename , typename> class Container,
          typename T1, typename T2>
void myfunc(const Container<T1*, T2> & c);

Конкретно, ваша функция должна быть вариацией этого:

template <template <typename> class Container, typename T>
void myfunc(const boost::ptr_list<A<Container::<T*> > > &);
...