标准 type_traits 库会产生一些使用 decltype 的类型别名的意外行为
The standard type_traits library produces unexpected beavior with some type aliases that use decltype
让我举例说明。我们以 std::is_same_v 和 std::is_base_of_v 为例。考虑以下代码:
#include <iostream>
#include <array>
#include <type_traits>
using namespace std;
struct base {};
struct derived : base { int foo; };
array<derived, 10> my_array;
int main()
{
using c1 = decltype(*begin(my_array));
using c2 = derived;
if constexpr(is_same_v<c1,c2>)
{
cout<<"Correct!"<<endl;
}
else
{
cout << "No luck even though:" << endl
<< "c1 type is " << typeid(c1).name() << endl
<< "c2 type is " << typeid(c2).name() << endl;
}
if constexpr(is_base_of_v<base, c1>)
{
cout<<"Correct!"<<endl;
}
else
{
cout << "No luck even though:" << endl
<< "is_base_of_v<base, derived> = " << is_base_of_v<base, derived> << endl;
}
return 0;
}
预期结果是:
Correct!
Correct!
但是,在 clang 10 和 gcc 11 中的实际结果是:
No luck even though:
c1 type is 7derived
c2 type is 7derived
No luck even though:
is_base_of_v<base, derived> = 1
头脑发热。我主要感兴趣的是找出此行为背后的确切原因,然后可能会找到解决方法。如果可能的话,解决方法应该适用于任何可迭代类型,并且只适用于 std::array.
你的问题是你有额外的参考:
using c1 = decltype(*begin(my_array)); // derived&
using c2 = derived;
is_same_v<derived, derived&>
为假。
std::decay_t
or std::remove_reference_t
可能会有帮助。
与typeid相同:
- Refers to a std::type_info object representing the type type. If type is a reference type, the result refers to a std::type_info object representing the referenced type.
另一种了解类型的方法是使用该技巧:
template <typename> struct Debug; /*No definition*/
Debug<c1> d; // Incomplete type
错误消息类似于
error: aggregate 'Debug<derived&> d
' has incomplete type and cannot be defined
让我举例说明。我们以 std::is_same_v 和 std::is_base_of_v 为例。考虑以下代码:
#include <iostream>
#include <array>
#include <type_traits>
using namespace std;
struct base {};
struct derived : base { int foo; };
array<derived, 10> my_array;
int main()
{
using c1 = decltype(*begin(my_array));
using c2 = derived;
if constexpr(is_same_v<c1,c2>)
{
cout<<"Correct!"<<endl;
}
else
{
cout << "No luck even though:" << endl
<< "c1 type is " << typeid(c1).name() << endl
<< "c2 type is " << typeid(c2).name() << endl;
}
if constexpr(is_base_of_v<base, c1>)
{
cout<<"Correct!"<<endl;
}
else
{
cout << "No luck even though:" << endl
<< "is_base_of_v<base, derived> = " << is_base_of_v<base, derived> << endl;
}
return 0;
}
预期结果是:
Correct!
Correct!
但是,在 clang 10 和 gcc 11 中的实际结果是:
No luck even though:
c1 type is 7derived
c2 type is 7derived
No luck even though:
is_base_of_v<base, derived> = 1
头脑发热。我主要感兴趣的是找出此行为背后的确切原因,然后可能会找到解决方法。如果可能的话,解决方法应该适用于任何可迭代类型,并且只适用于 std::array.
你的问题是你有额外的参考:
using c1 = decltype(*begin(my_array)); // derived&
using c2 = derived;
is_same_v<derived, derived&>
为假。
std::decay_t
or std::remove_reference_t
可能会有帮助。
与typeid相同:
- Refers to a std::type_info object representing the type type. If type is a reference type, the result refers to a std::type_info object representing the referenced type.
另一种了解类型的方法是使用该技巧:
template <typename> struct Debug; /*No definition*/
Debug<c1> d; // Incomplete type
错误消息类似于
error: aggregate '
Debug<derived&> d
' has incomplete type and cannot be defined