问题
I am trying to find a way to get the base class of a template parameter.
Consider the following class:
template <class C>
class Foo
{
public:
Foo(){};
~Foo(){};
C* ptr;
};
if C is a reference (e.g. Test&) then ptr is type C&*
But I need to get a pointer the base class whether C is a reference, a pointer or anything else.
- if C is Test& then ptr need to be Test*,
- if C is Test* then ptr needs to be Test*,
- if C is Test then ptr needs to be Test*, etc.
Is there anyway to get the "base" class of C so I can create the pointer I need ?
回答1:
How about using std::remove_reference?
#include <type_traits>
template <class C>
class Foo
{
public:
Foo(){};
~Foo(){};
std::remove_reference<C>::type *ptr;
};
回答2:
If you really need the underlying element type, you can use recursive applications of the removal type manipulation traits:
#include <type_traits>
// precv = pointer, reference, extents, const, and volatile
template <typename T>
struct remove_precv
{
typedef typename std::remove_pointer<
typename std::remove_reference<
typename std::remove_all_extents<
typename std::remove_cv<T>::type>::type>::type>::type type;
};
template <typename T, typename U>
struct element_type_impl
{
typedef typename element_type_impl<
typename remove_precv<T>::type, T>::type type;
};
template <typename T>
struct element_type_impl<T, T>
{
typedef T type;
};
template <typename T>
struct element_type
{
struct null_type { };
typedef typename element_type_impl<T, null_type>::type type;
};
For example, element_type<int***[42]>::type is int.
回答3:
Do this:
#include <type_traits>
template <typename T>
class Foo
{
typedef typename std::remove_pointer<typename std::decay<T>::type>::type C;
// ...
};
decay removes references and CV-qualifications, and remove_pointer removes pointers.
回答4:
You can do this with a little bit of template meta-programming, for example:
#include <cassert>
#include <typeinfo>
template <typename T>
struct unpoint {
typedef T type;
};
template <typename T>
struct unpoint<T*> {
typedef typename unpoint<T>::type type;
};
int main() {
int *a;
int **b;
int ***c;
int ****d;
const std::type_info& t1=typeid(unpoint<decltype(a)>::type);
const std::type_info& t2=typeid(unpoint<decltype(b)>::type);
const std::type_info& t3=typeid(unpoint<decltype(c)>::type);
const std::type_info& t4=typeid(unpoint<decltype(d)>::type);
assert(t1 == t2);
assert(t1 == t3);
assert(t1 == t4);
}
Where the specialisation of unpoint removes the pointer and recursively calls itself until there are no pointers left in the type.
来源:https://stackoverflow.com/questions/10323018/how-to-get-t-from-t-t-or-t-template-parameter