如何检查两种类型是否相同,忽略const和参考

How to check if two types are the same, ignoring const and reference?

本文关键字:忽略 const 参考 是否 类型 何检查 检查 两种      更新时间:2023-10-16

在C 中,可以使用std::is_same检查两种类型是否完全相同。是否有一种方法可以检查两种类型是否相同,除了const&修饰符吗?这是一个示例:

#include <type_traits>
#include <iostream>
using namespace std;
int main() {
    cout << boolalpha;
    cout << is_same<char,int>::value << endl;    // false - OK
    cout << is_same<char,char>::value << endl;   // true  - OK
    cout << is_same<char,const char>::value << endl;  // false - should be true
    cout << is_same<char,const char&>::value << endl; // false - should be true
}

删除CV-Qualifiers以及返回非参考类型将由 C 20 启用。std :: remove_cvref

但是,从当前标准开始,您可以使用类型的修改功能在Conunction

中使用
template<class T1, class T2>
void print_is_same() {
  std::cout << std::is_same<T1, T2>() << 'n';
}
int main() {
  std::cout << std::boolalpha;
  print_is_same<char, int>(); //false
  print_is_same<char, char>(); //true
  print_is_same<char, std::remove_const<const char>::type>(); //true
  print_is_same<char, std::remove_const<std::remove_reference<const char &>::type>::type>(); //true
}

或可能创建类型的别名,例如

template<typename T>
using base_type = typename std::remove_cv<typename std::remove_reference<T>::type>::type;

我找到了一个替代解决方案:我们可以添加它们:

,而不是删除const and&amp;
template<class T1, class T2>
bool is_almost_same_v = std::is_same_v<const T1&,const T2&>;

确实:

cout << is_almost_same_v<char,int> << endl;    // false
cout << is_almost_same_v<char,char> << endl;   // true
cout << is_almost_same_v<char,const char> << endl;  // true
cout << is_almost_same_v<char,const char&> << endl; // true

在许多情况下, std::is_same_v<std::decay_t<TYPE_TO_TEST>, TYPE_TO_COMPARE>会解决问题。std::decay_t<TYPE>还将数组类型转换为指针转换为数组成员,因此std::is_same_v<std::decay_t<int[5]>, int*>也会产生正确。但是在许多情况下,这种行为甚至是有益的,尤其是如果您的测试要求"可以像指针"。

仅剥离顶级cvref-qualifiers,答案就是

template<class T, class U>
inline constexpr bool is_same_uncvref_v = std::is_same_v<
    std::remove_cvref_t<T>,
    std::remove_cvref_t<U>
>;

或,pre-c 20,

template<class T, class U>
inline constexpr bool is_same_uncvref_v = std::is_same_v<
    std::remove_cv_t<std::remove_reference_t<T>>,
    std::remove_cv_t<std::remove_reference_t<U>>
>;

正如上面指出的Erel(几乎(,这等同于

template<class T, class U>
inline constexpr bool is_same_uncvref_v = std::is_same_v<
    const volatile std::remove_reference_t<T>,
    const volatile std::remove_reference_t<U>
>;

仍然,这无法检测int*const int*之间的相似性,或const int**int *const *之间的相似性。对于这种相似性,我们需要[Cons.Qual]/2的"类似类型"的概念。请参阅基于C 标准的定义实现" IS_SIMILAR"类型特征。我在我的libc 叉中实现该特征如下:

template <class _Tp, class _Up>
struct is_similar : conditional<
        is_const<_Tp>::value || is_volatile<_Tp>::value ||
            is_const<_Up>::value || is_volatile<_Up>::value,
        is_similar<typename remove_cv<_Tp>::type, typename remove_cv<_Up>::type>,
        is_same<_Tp, _Up>
    >::type {};
template <class _Tp, class _Up>
struct is_similar<_Tp*, _Up*>: is_similar<_Tp, _Up> {};
template <class _Tp, class _Up, class _Cp>
struct is_similar<_Tp _Cp::*, _Up _Cp::*>: is_similar<_Tp, _Up> {};
template <class _Tp, class _Up>
struct is_similar<_Tp[], _Up[]>: is_similar<_Tp, _Up> {};
template <class _Tp, class _Up, size_t _Np>
struct is_similar<_Tp[], _Up[_Np]>: is_similar<_Tp, _Up> {};
template <class _Tp, class _Up, size_t _Np>
struct is_similar<_Tp[_Np], _Up[]>: is_similar<_Tp, _Up> {};
template <class _Tp, class _Up, size_t _Np>
struct is_similar<_Tp[_Np], _Up[_Np]>: is_similar<_Tp, _Up> {};