10

对于参数类 C,无论指针、常量或引用修饰符如何,我都希望始终获得“原始”类型。

template<typename __T>
class C
{
public:
    typedef std::some_magic_remove_all<__T>::type T;
}

int main()
{
    C<some_type>::type a;
}

例如,对于some_type等于:

  • int&
  • int**
  • int*&
  • int const &&
  • int const * const
  • 等等

我想要a的总是类型int。我怎样才能实现它?

4

3 回答 3

12

如果你想更多地使用标准库,你可以这样做:

#include <type_traits>
template<class T, class U=
  typename std::remove_cv<
  typename std::remove_pointer<
  typename std::remove_reference<
  typename std::remove_extent<
  T
  >::type
  >::type
  >::type
  >::type
  > struct remove_all : remove_all<U> {};
template<class T> struct remove_all<T, T> { typedef T type; };

它会删除东西,直到不再改变类型。使用更新的标准,这可以缩短为

template<class T, class U=
  std::remove_cvref_t<
  std::remove_pointer_t<
  std::remove_extent_t<
  T >>>>
  struct remove_all : remove_all<U> {};
template<class T> struct remove_all<T, T> { typedef T type; };
template<class T> using remove_all_t = typename remove_all<T>::type;
于 2013-01-25T13:45:21.870 回答
11
template<class T> struct remove_all { typedef T type; };
template<class T> struct remove_all<T*> : remove_all<T> {};
template<class T> struct remove_all<T&> : remove_all<T> {};
template<class T> struct remove_all<T&&> : remove_all<T> {};
template<class T> struct remove_all<T const> : remove_all<T> {};
template<class T> struct remove_all<T volatile> : remove_all<T> {};
template<class T> struct remove_all<T const volatile> : remove_all<T> {};
//template<class T> struct remove_all<T[]> : remove_all<T> {};
//template<class T, int n> struct remove_all<T[n]> : remove_all<T> {};

我最初也剥离了范围(数组),但 Johannes 注意到这会导致 的歧义const char[],并且问题没有提及它们。如果我们还想剥离数组(另请参阅评论中提到的想法),以下内容不会使事情变得太复杂:

#include <type_traits>
template<class U, class T = typename std::remove_cv<U>::type>
struct remove_all { typedef T type; };
template<class U, class T> struct remove_all<U,T*> : remove_all<T> {};
template<class U, class T> struct remove_all<U,T&> : remove_all<T> {};
template<class U, class T> struct remove_all<U,T&&> : remove_all<T> {};
template<class U, class T> struct remove_all<U,T[]> : remove_all<T> {};
template<class U, class T, int n> struct remove_all<U,T[n]> : remove_all<T> {};

或使用辅助类但只有一个模板参数:

#include <type_traits>
template<class T> struct remove_all_impl { typedef T type; };
template<class T> using remove_all =
  remove_all_impl<typename std::remove_cv<T>::type>;
template<class T> struct remove_all_impl<T*> : remove_all<T> {};
template<class T> struct remove_all_impl<T&> : remove_all<T> {};
template<class T> struct remove_all_impl<T&&> : remove_all<T> {};
template<class T> struct remove_all_impl<T[]> : remove_all<T> {};
template<class T, int n> struct remove_all_impl<T[n]> : remove_all<T> {};

如果所有变体开始看起来都差不多,这是正常的;-)

于 2013-01-25T13:21:48.720 回答
1

您也可以使用该remove_cvref_t功能,它从 c++20 开始可用

#include <iostream>
#include <type_traits>


int main()
{
    std::cout << std::boolalpha
              << std::is_same_v<std::remove_cvref_t<int>, int> << '\n'
              << std::is_same_v<std::remove_cvref_t<int&>, int> << '\n'
              << std::is_same_v<std::remove_cvref_t<int&&>, int> << '\n'
              << std::is_same_v<std::remove_cvref_t<const int&>, int> << '\n'
              << std::is_same_v<std::remove_cvref_t<const int[2]>, int[2]> << '\n'
              << std::is_same_v<std::remove_cvref_t<const int(&)[2]>, int[2]> << '\n'
              << std::is_same_v<std::remove_cvref_t<int(int)>, int(int)> << '\n';
}
于 2019-05-15T10:10:35.720 回答