简体   繁体   English

c++ useless-cast from size_t to uint32_t for different targets

[英]c++ useless-cast from size_t to uint32_t for different targets

I have some code that builds for different targets.我有一些为不同目标构建的代码。 It also has some legacy functions that take uint32_t instead of size_t - which is annoying when I want to cast size_t types to it - with the levels of warnings that we have set (lots of gcc warnings).它还具有一些使用 uint32_t 而不是 size_t 的遗留函数 - 当我想将 size_t 类型转换为它时,这很烦人 - 具有我们设置的警告级别(大量 gcc 警告)。

So here is a contrived example:所以这是一个人为的例子:

val32 = static_cast<uint32_t>(strings.size());
val64 = static_cast<uint64_t>(strings.size());  // ERROR

Depending on which arch this runs on, one of the two lines above will complain with useless cast warning (which we treat as errors).根据运行的拱门,上面两行之一将抱怨无用的强制转换警告(我们将其视为错误)。 Now I know there are some ways around this like, change the code to take size_t... but, that is not my question.现在我知道有一些方法可以解决这个问题,将代码更改为 size_t ... 但是,这不是我的问题。 My question is, when this situation arises, how can I best tackle this.我的问题是,当这种情况出现时,我怎样才能最好地解决这个问题。

I have come up with a solution - but it requires reference passing of variables:我想出了一个解决方案 - 但它需要变量的引用传递:

template<typename TO, typename FROM>
TO static_cast_if_different(const FROM &value)
{
    if constexpr (std::is_same_v<TO, FROM>)
        return value;
    else
        return static_cast<TO>(value);
}

Now this works, but I feel there is a better way (perhaps built in to the standard - or an improvement of what I have done here)?现在这可行,但我觉得有更好的方法(也许内置在标准中 - 或者我在这里所做的改进)?

See the full example code here: https://godbolt.org/z/87hao1aTb在此处查看完整的示例代码: https://godbolt.org/z/87hao1aTb

full list of warning flags for gcc: -Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wunreachable-code -Wlogical-op -Wshadow -Wmissing-include-dirs -Wparentheses -Wmisleading-indentation -Werror -Wno-psabi -Wno-error=deprecated-declarations -Wnon-virtual-dtor -Wuseless-cast -Wduplicated-cond -Wnull-dereference gcc 警告标志的完整列表: -Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wunreachable-code -Wlogical-op -Wshadow -Wmissing-include-dirs -Wparentheses -Wmisleading-indentation -Werror -Wno-psabi -Wno-error=deprecated-declarations -Wnon-virtual-dtor -Wuseless-cast -Wduplicated-cond -Wnull-dereference

Note: I don't want to remove the useless-cast warning flag as that is useful else where注意:我不想删除 useless-cast 警告标志,因为这在其他地方很有用

It is a good solution, and it can still be improved somewhat.这是一个很好的解决方案,它仍然可以有所改进。

  1. The cast and the std::is_same_v are not really necessary.演员表和std::is_same_v并不是真正必要的。 A simple assignment will do exactly the same thing (when working with unsigned integral types, but we want to check for that).一个简单的赋值将做完全相同的事情(当使用unsigned整数类型时,但我们想检查一下)。 The function could look like this: function 可能如下所示:

     template<typename TO, typename FROM> TO legacy_size_cast(FROM value) { static_assert(std::is_unsigned_v<FROM> && std::is_unsigned_v<TO>, "Only unsigned types can be cast here;"); TO result = value; return result; }

    You will still have a visual indication of a type conversion at the call site, which I suppose is what you're after.您仍然会在调用站点上看到类型转换的视觉指示,我想这就是您所追求的。 But if you do need an actual cast for some reason, you can still add it:但是如果你出于某种原因确实需要一个实际的演员表,你仍然可以添加它:

     TO result = static_cast<TO>(value);
  2. You can protect against accidental overflow by adding this:您可以通过添加以下内容来防止意外溢出:

     assert(result == value);

    This might not look like something terribly useful (who is going to allocate a single 4GB object?) but actually it can catch nasty bugs when you pass a negative offset, eg (uint64_t)(-1) .这可能看起来不是非常有用的东西(谁将分配一个 4GB object?)但实际上它可以在传递负偏移量时捕获令人讨厌的错误,例如(uint64_t)(-1) This is actually a huge positive value, but it behaves like a -1 in arithmetic... until you convert it to uint32_t and then back to uint64_t , then it suddenly doesn't, and the assert will catch that.这实际上是一个巨大的正值,但它在算术中的行为类似于-1 ......直到您将其转换为uint32_t ,然后再转换为uint64_t ,然后它突然没有了,并且assert会抓住它。

  3. It does not matter if you pass by reference or by value.是通过引用还是通过值都没有关系。 In a release build, the function is going to be inlined and optimized away completely anyway.在发布版本中,无论如何 function 将被内联并完全优化掉。

I would recommend using macros.我建议使用宏。 Eg例如

#ifdef SOME_ARCH
code
#else
other code
#endif

Then when you compile for some_arch, add -D SOME_ARCH to the compile flags.然后在为 some_arch 编译时,将-D SOME_ARCH添加到编译标志。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 C++ 中转换字节向量(std::vector<uint8_t> ) 到不同的 uint32_t、uint16_t 和 uint8_t 变量中</uint8_t> - How to cast, in C++, a byte vector (std::vector<uint8_t>) into different uint32_t, uint16_t and uint8_t variables 从C ++发送uint32_t到Java - Send uint32_t from C++ to Java 在C ++中将uint8_t *转换为uint32_t * - Casting an uint8_t* to uint32_t* in c++ 如何在 C++ 中异步地从/向 uint32_t 存储和弹出 uint8_t? - How to store and pop uint8_t from/to uint32_t asynchronously in C++? 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 uint32_t 作为向量索引在 64 位中比 size_t 具有更好的性能 - uint32_t as vector index has better performance than size_t in 64-bit 为什么std :: uint32_t与uint32_t不同? - Why is std::uint32_t different from uint32_t? 将实现特定的C ++字符与Python中的uint32_t匹配 - Match implementation specific C++ char to uint32_t cast in Python 在 C 或 C++ 中,uint64_t 的 memory 布局是否保证与 uint32_t[2] 相同? 可以将一个转换为另一个吗? - In C or C++, is memory layout of uint64_t guaranteed to be the same as uint32_t[2] ? Can one be cast as the other? 为什么在 Mac OS X 上使用 size_t 时 uint32_t 和 uint64_t 之间存在歧义? - Why is there ambiguity between uint32_t and uint64_t when using size_t on Mac OS X?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM