c++ 针对不同目标从 size_t 到 uint32_t 的无用转换

如何解决c++ 针对不同目标从 size_t 到 uint32_t 的无用转换

我有一些针对不同目标构建的代码。它还具有一些使用 uint32_t 而不是 size_t 的遗留函数 - 当我想将 size_t 类型转换为它时这很烦人 - 具有我们设置的警告级别(很多 gcc 警告)。

所以这是一个人为的例子:

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

根据它运行在哪个拱门上,上面两行之一会抱怨无用的强制转换警告(我们将其视为错误)。现在我知道有一些方法可以解决这个问题,例如更改代码获取 size_t... 但是,这不是我的问题。我的问题是,当出现这种情况时,我该如何最好地解决这个问题。

我想出了一个解决方案 - 但它需要变量的引用传递:

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);
}

在这有效,但我觉得有更好的方法(也许内置于标准中 - 或者我在这里所做的改进)?

在此处查看完整示例代码https://godbolt.org/z/87hao1aTb

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

注意:我不想删除 useless-cast 警告标志,因为它在其他地方很有用

解决方法

这是一个很好的解决方案,它仍然可以有所改进。

  1. 演员表和 std::is_same_v 并不是真正必要的。一个简单的赋值将做完全相同的事情(当使用 unsigned 整数类型时,但我们想要检查它)。该函数可能如下所示:

     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;
     }
    

    您仍然可以在呼叫站点看到类型转换的视觉指示,我想这就是您所追求的。但是如果你出于某种原因确实需要一个实际的演员,你仍然可以添加它:

     TO result = static_cast<TO>(value);
    
  2. 您可以通过添加以下内容来防止意外溢出:

     assert(result == value);
    

    这可能看起来不太有用(谁会分配一个 4GB 的对象?)但实际上,当您传递负偏移量时,它可以捕获令人讨厌的错误,例如(uint64_t)(-1)。这实际上是一个巨大的正值,但它在算术中表现得像 -1 ......直到你将它转换为 uint32_t 然后再转换回 uint64_t,然后它突然没有, assert 会捕捉到这一点。

  3. 无论是按引用还是按值传递都没有关系。在发布版本中,该函数无论如何都将被内联并完全优化掉。

,

我建议使用宏。 例如

#ifdef SOME_ARCH
code
#else
other code
#endif

然后当您为 some_arch 编译时,将 -D SOME_ARCH 添加到编译标志中。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?