首页 > 解决方案 > 如何将任何化合物还原为非化合物类型

问题描述

要求:给定复合类型“T”,用作基本类型的非复合类型是什么?

到目前为止,我的尝试是这个模板别名:

template <class T>
using reduce_to_non_compound_t = 
    std::remove_all_extents_t< 
       std::remove_pointer_t< 
         std::remove_cvref_t < T > 
     > >;

例如

  // array of pointers to string
    using arr_of_sp = std::string * (&)[42];

  // should pass
  static_assert( std::is_same_v<
       std::string,
        reduce_to_non_compound_t<arr_of_sp>
   >  )

测试这一点的许多用例可能非常大。在我进一步讨论之前,我想问一下是否有人有更好的想法甚至实施?

我在问这样的事情是否合乎逻辑。这就是用例出现的地方。如果它是合乎逻辑的,那么它可以被编写。

标签: c++c++17c++20

解决方案


如果,正如你所说,你只是想从一个类型中去除 cv 限定符、指针、引用和范围,那么你可以使用这个:

template <typename T, typename = void> struct base {using type = std::remove_cv_t<T>;};

template <typename T> using base_t = typename base<T>::type;

template <typename T> struct base<T, std::enable_if_t<std::is_array_v<T>>>
{using type = base_t<std::remove_all_extents_t<T>>;};

template <typename T> struct base<T, std::enable_if_t<std::is_reference_v<T>>> 
{using type = base_t<std::remove_reference_t<T>>;};

template <typename T> struct base<T, std::enable_if_t<std::is_pointer_v<T>>> 
{using type = base_t<std::remove_pointer_t<T>>;};

用法:

static_assert(std::is_same_v<int, base_t<const int *volatile[4]>>);

它可以很容易地扩展为使用成员函数指针、函数或其他东西。


推荐阅读