C++ 从‘std::__tuple... {aka ‘unsigned int*’} 转换为‘uint32_t’ {aka ‘unsigned int’} 失去精度

C++ Cast from ‘std::__tuple... {aka ‘unsigned int*’} to ‘uint32_t’ {aka ‘unsigned int’} loses precision

您可能不得不原谅我,因为我是 C++ 的新手并且可能在我编写的代码中犯了一些基本错误。

static tuple<read_result, uint8_t*> m_scan_record(bool skip, uint32_t& size, FILE* file)
{
    read_result result;
    
    tuple<read_result, uint32_t*> rd_rec_size_result = m_read_generic_t<uint32_t>(file);

    result = (read_result)get<0>(rd_rec_size_result);
    
    if (result != read_success )
    {
        return tuple<read_result, uint8_t*>(result, nullptr);
    }

    size = (uint32_t) get<1>(rd_rec_size_result);

    if ( skip )
    {
        fseek(file, size, SEEK_CUR);
    }
// ...
}

template<typename T>
static tuple<read_result, T*> m_read_generic_t(FILE* file)
{
    T ret = 0;
    
    read_result result = m_read_from_file_to_buffer(&ret, sizeof(T), file);

    if (result == read_success)
    {
        return tuple<read_result, T*>(result, &ret);
    }

    return tuple<read_result, T*>(result, nullptr);
}

当我编译此代码时出现此错误:

cast from ‘std::__tuple_element_t<1, std::tuple<read_result, unsigned int*> >’ {aka ‘unsigned int*’} to ‘uint32_t’ {aka ‘unsigned int’} loses precision [-fpermissive]

我的意图和期望do/happen:

  1. m_scan_record 的声明中,size 参数用 & 声明,目的是允许我通过引用传递值,类似使用 REF c# 关键字

  2. 我调用了通用(模板)函数 m_read_generic_t,它是用指定类型 <unit32_t> 调用的,因此(根据其定义)将 return 一种 tuple<read_result, uint32_t*>

  3. 一旦我有了 m_read_generic_t 编辑的元组 return,我想获取元组的第二个值指向的 unit32_t 值,并且将该值放入上面第 1 点提到的 size 变量中,然后调用函数可能可以访问堆栈上一级。

  4. 从以上几点你可以看到我的意图(我明白我可能在现实中很遥远!)是在这一行:

    大小 = (uint32_t) 得到<1>(rd_rec_size_result);

我所做的只是获取一个 'pointed to' 值并将其放入匹配类型的变量中,就像经常引用的教科书示例:

uint32_t v = 123;
uint32_t* ptr_to_v = &v;
uint32_t x = ptr_to_v;   // x == 123

很明显,这不是我的代码真正发生的事情,因为如果是这样,我认为就不需要强制转换了。但是如果我删除它,像这样:

size = get<1>(rd_rec_size_result);

然后我得到一个编译时错误:

a value of type "std::__tuple_element_t<1UL, std::tuple<read_result, uint32_t *>>" cannot be assigned to an entity of type "uint32_t"

因此我认为我做错了很多事 - 但我不知道是什么。这与我从元组中取出指针的方式有关吗?或者在从 uint32_t* 中获取 uint32_t 值时是否还有其他事情发生?

这一切都在 Ubuntu 20.04 的 C++ 环境中,FWIW

非常感谢 any/all 的建议;请放轻松!

tuple<read_result, uint32_t*> rd_rec_size_result = ...

这个元组的第二个成员,如这里明确声明的,是一个指向 uint32_t 的指针。这就是 uint32_t * 在 C++ 中的意思。

size = (uint32_t) get<1>(rd_rec_size_result);

这会检索 uint32_t * 并尝试将其转换为 uint32_t。 C++ 不是这样工作的。尽管可以强制执行此转换,但您的编译器完全有权利相信此代码试图执行的任何操作都一定是错误的。

也许一开始我想知道,您的意图是取消引用指针。无论如何,这就是编译错误的原因。如果你的意图是,真的,取消引用这个指针,那么这将是一个简单的问题,将它更改为

size = *get<1>(rd_rec_size_result);

但是,这不会是您的麻烦的终结。即使在修复了这个编译错误之后,这样,显示的代码仍然会非常非常糟糕。

这是因为 m_read_generic_t returns 是一个指向本地对象的指针,当函数 returns 时,它会被销毁,并试图取消引用这个指针,在这里,将使demons fly out of your nose.

这里的real修复是将m_read_generic_t改为notreturn 一个指针首先作为元组中的第二个值,从而首先消除了编译错误。