How to get T* from T, T& or T* template parameter

霸气de小男生 提交于 2020-01-02 20:06:53

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!