当前位置: 首页 > 知识库问答 >
问题:

标准type_traits库生成意外的beavior,其中某些类型别名使用了decltype

施鸿
2023-03-14

让我举例说明。让我们以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个答案

郑光济
2023-03-14

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

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

错误消息类似于

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

演示

 类似资料:
  • 标准库提供了很多自定义类型,在原生类型基础上进行了大量扩充。这是部分自定义类型: 可增长的 String(可增长的字符串),如: "hello world" 可增长的 vector: [1, 2, 3] 选项类型(optional types): Option<i32> 错误处理类型(error handling types): Result<i32, i32> 堆分配的指针(heap alloc

  • panic! 宏可用于产生一个 panic (恐慌),并开始展开它的栈。在展开栈的同时,运行时将会释放该线程所拥有的所有资源,是通过调用对象的析构函数完成。 因为我们正在处理的程序只有一个线程,panic! 将会引发程序上报 panic 消息并退出。 // 再次实现整型的除法(/) fn division(dividend: i32, divisor: i32) -> i32 { if d

  • 问题内容: 阅读MDN生成器的文档后,我想到了一个简单的实验: 在设置了标志的node.js v0.11.9上运行它会产生以下错误: 我也尝试使用and 关键字代替,但是没有成功。 我不明白到底是什么,但是如果我在循环中使用它,我会得到: 如果我用输出替换for中的收益,则和。我究竟做错了什么? 编辑 这是一个简约的生成器,显示node.js知道如何处理生成器: 输出: 解决方案(感谢@Andre

  • 我们前面已经看到 Option 枚举可以用于函数可能失败的返回值,其中 None 可以返回以表明失败。但是有时要强调为什么一个操作会失败。为达成这点,我们提供了 Result 枚举。 Result<T, E> 枚举拥有两个变量: Ok(value) 表示操作成功,并装包操作返回的 value(value 拥有 T 类型)。 Err(why),表示操作失败,并装包 why,它(能按照所希望的方式)解

  • 有时候想要捕捉到程序某部分的失败信息,而不调用 panic!;这可使用 Option 枚举来完成。 Option<T> 枚举有两个变量: None,表明失败或缺少值 Some(value),元组结构体,使用 T 类型装包了一个值 value // 不会 `panic!` 的整数除法。 fn checked_division(dividend: i32, divisor: i32) -> Optio

  • 在我的spring上下文中,我创建了一个服务bean和这个服务bean的代理(显式)。两者实现相同的接口。 有什么想法吗?