函数模板参数的复杂类型推导

时间:2011-09-01 15:07:17

标签: c++ templates typedef

我有另一个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 个答案:

答案 0 :(得分:2)

使用部分特化来删除指针是微不足道的:

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;

答案 1 :(得分:0)

如果你真的无法从类typedef推断出正确的类型(我怀疑,请仔细检查文档),你可以更明确地指定模板参数:

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*> > > &);

答案 2 :(得分:0)

  

问题1:EasyLookingObject :: value_type确实给了我一个指针类型。如何从中推导出完整类型并在typedef中使用它?

您可能不需要提取typedef。

将每个提取的项目传递给另一个重载函数。使用类似于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
    }
}