提问者:小点点

标准type_traits库生成意外的beavior,其中某些类型别名使用了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和GCC11中的实际结果都是:

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。


共1个答案

匿名用户

您的问题是您有额外的参考:

using c1 = decltype(*begin(my_array)); // derived&
using c2 = derived;

is_same_v为false。

std::decay_tstd::remove_reference_t可能有所帮助。

和typeid相同:

  1. 引用表示type类型的std::type_info对象。如果type是引用类型,则结果引用表示引用类型的std::type_info对象。

另一种了解类型的方法是使用这个技巧:

template <typename> struct Debug; /*No definition*/

Debug<c1> d; // Incomplete type

错误消息类似于

错误:聚合“debugd”的类型不完整,无法定义

演示