The answer to this question has general application, but I will motivate it with the following example:
I have the following template class:
template <typename V>
class Collection
{
public:
struct id{};
struct name{};
// A collection parameterized by type V that is indexed by a string 'name'
// and a integer 'id'
// The type V must implement 'get_id()' and a 'get_name()' functions
typedef multi_index_container <
V,
indexed_by<
ordered_unique<
tag<id>, const_mem_fun<V, unsigned int, &V::get_id> >,
ordered_unique<
tag<name>, const_mem_fun<V, std::string, &V::get_name> >
>
> ni_collection;
>
I want to modify this template so that I can create a collection with the objects, their pointers or their references: Collection<Obj>
, Collection<std::unique_ptr<Obj>>
or Collection<Obj *>
.
How would I modify my template to achieve this?
--- UPDATE --- I had posted a related question here: Computing The Type Of A Function Pointer
Synthesizing the excellent answers in both places, I have finally achieved my original goal. Here are the details of my current implementation:
template <typename V>
class Collection
{
private:
// A type-level function that returns the undecorated type of the object
// So unrwap_object_type<Widget *> = Widget
// unwrap_object_type<std::unique_ptr<Widget>> = Widget
// unwrap_object_type<Widget> = Widget
template<typename T, typename = void>
struct unwrap_object_type { typedef T type; };
template <typename T>
struct unwrap_object_type<T *, void> { typedef T type; };
template<typename T>
struct unwrap_object_type<T,
typename std::conditional<false,
typename T::element_type, void>::type>
{
typedef typename T::element_type type;
};
////
// So that QHNETO_COLLECTION<Widget>, QHNETO_COLLECTION<Widet *>,
// and QHNETO_COLLECTION<std::unique_ptr<Widget>> are valid
typedef typename unwrap_object_type<V>::type W;
// Tags for the two indices (id and name) of the collection
struct id;
struct name;
// A collection parameterized by type V that is indexed by a string 'name'
// and a integer 'id'
// The type V must implement 'get_id()' and a 'get_name()' functions
typedef multi_index_container <
V,
indexed_by<
ordered_unique<
tag<id>,
const_mem_fun<W, unsigned int, &W::get_id> >,
ordered_unique<
tag<name>,
const_mem_fun<W, std::string, &W::get_name> >
>
> ni_collection;
ni_collection m_collection;
};