Complex type deduction from function template parameter
I have another C++ template question. I am a lazy guy, so I try to not specify template arguments if possible. Now I have a function
template< typename EasyLookingObject >
void myfunct( EasyLo开发者_JS百科okingObject& obj ) {
//do something with obj
}
Now, EasyLookingObject is in fact a
boost::ptr_list< A< STDContainer::<TargetType*> > >
In order to work with obj, I need to know the types of STDContainer and TargetType. Can you help me to get these types?
Problem 1: EasyLookingObject::value_type does give me a pointer type. How do I deduce the full type from it and use it within a typedef?
The same probably applies to the STDContainer::value_type issue.
Removing the pointer is trivial using partial specialisation:
template <typename T>
struct remove_ptr {
typedef T type;
};
template <typename T>
struct remove_ptr<T*> : remove_ptr<T> { };
(I’m sure Boost also has something like this.)
Putting it all together:
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;
Problem 1: EasyLookingObject::value_type does give me a pointer type. How do I deduce the full type from it and use it within a typedef?
You probably don't need to extract the typedefs.
Just pass every extracted item to another overloaded function. Use an extractor function akin to boost::get_pointer()
to extract a pointer from a reference, or a plain or smart 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
}
}
If you really can't infer the correct types from class typedefs (which I doubt, double check the documentation), the you can specify the template parameters a bit more explicitly:
template <template <typename...> class Container, typename T, typename ...Args>
void myfunc(const Container<T*, Args...> & c)
{
// ...
}
If you don't have variadic templates, you'll have to specify as many arguments as your container takes, or specify default arguments if you only want the template to match those. Here's a defaulting version that works for two-parameter containers:
template <template <typename A, typename = std::allocator<A> > class Container,
typename T>
void myfunc(const Container<T*> & c);
This will only match Container<T*, std::allocator<T*>>
. Here's a general version for two-parameter containers:
template <template <typename , typename> class Container,
typename T1, typename T2>
void myfunc(const Container<T1*, T2> & c);
Concretely, your function should be a variation of this:
template <template <typename> class Container, typename T>
void myfunc(const boost::ptr_list<A<Container::<T*> > > &);
精彩评论