如何检查两种类型是否相同,忽略const和参考
How to check if two types are the same, ignoring const and reference?
在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> {};