【问题标题】:How to get T* from T, T& or T* template parameter如何从 T、T& 或 T* 模板参数中获取 T*
【发布时间】:2012-05-06 13:43:20
【问题描述】:

我正在尝试找到一种方法来获取模板参数的基类。

考虑以下类:

template <class C>
class Foo
{
    public:
        Foo(){};
        ~Foo(){};
        C* ptr;
};

如果 C 是一个引用(例如 Test&)那么 ptr 是类型 C&*

但无论 C 是引用、指针还是其他任何东西,我都需要获取基类的指针。

  • 如果 CTest& 那么 ptr 需要是 Test*
  • 如果 CTest* 那么 ptr 需要是 Test*
  • 如果 CTest 那么 ptr 需要是 Test* 等等。

有没有办法获得 C 的“基”类,这样我就可以创建我需要的指针了?

【问题讨论】:

  • 如果CTest***Test[1][2] 怎么办?还是Test const*
  • 我没有时间写一个完整的答案,但检查(即谷歌)参考和指针类型的部分模板专业化。
  • 关于这个主题的好书是:D. Vandevoorde, N.M. Josuttis “C++ 模板。完整指南”和 Alexandrescu “现代 C++ 设计:应用的通用编程和设计模式”。这些书籍包含大量此类示例,并提供了模板元编程技术(如特征和策略)的体验。

标签: c++ templates pointers reference


【解决方案1】:

如果你真的需要底层元素类型,你可以使用移除类型操作特征的递归应用:

#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;
};

例如,element_type&lt;int***[42]&gt;::typeint

【讨论】:

  • 我认为 std::decay 也可以在这里工作,而不是 remove_precv,正如 Kerrek SB 的回答中所述。我不熟悉这种操纵特性,我不太确定它的行为是什么。
  • decay 还会转换可能不需要的数组和函数类型(当然在 q 中我们只有类)。
【解决方案2】:

你可以通过一些模板元编程来做到这一点,例如:

#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);
}

unpoint 的特化删除指针并递归调用自身,直到类型中没有指针为止。

【讨论】:

    【解决方案3】:

    这样做:

    #include <type_traits>
    
    template <typename T>
    class Foo
    {
        typedef typename std::remove_pointer<typename std::decay<T>::type>::type C;
        // ...
    };
    

    decay 删除引用和 CV 限定,remove_pointer 删除指针。

    【讨论】:

      【解决方案4】:

      std::remove_reference怎么样?

      #include <type_traits>
      
      template <class C>
      class Foo
      {
          public:
              Foo(){};
              ~Foo(){};
              std::remove_reference<C>::type *ptr;
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-22
        • 1970-01-01
        • 2017-05-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多