【问题标题】:C++ - compilation error for all implicit conversionC++ - 所有隐式转换的编译错误
【发布时间】:2018-03-05 06:32:36
【问题描述】:

是否有一个编译器标志在任何隐式转换(如 int32_t 到 uint32_t)的情况下记录警告/错误。

#include <cstdint>
#include <iostream>


using ::std::int32_t;
using ::std::uint32_t;


int main(int argc, char *argv[])
{

   int32_t x = 9;

    uint32_t i = x;

    std::cout << " " << x << " " << i << std::flush << std::endl;

    return 0;
}

c++ -std=c++11 -Wall -Wconversion -Wpedantic cast.cpp

我在编译期间没有收到任何问题/警告/错误 - 有没有办法可以实现。

【问题讨论】:

标签: c++


【解决方案1】:
uint32_t i = x;

有符号 int 类型到无符号 int 类型的转换在 C++ 中有很好的定义。

(C++11,§4.7 ¶2)

如果目标类型是无符号的,则结果值是最小的 与源整数一致的无符号整数(模 2n 其中 n 是用于表示无符号类型的位数)。 [ 注意:在二进制补码表示中,这种转换是概念性的,位模式没有变化(如果没有截断)。 ——尾注]

【讨论】:

  • 谢谢 - 您能否详细解释一下上述 C++ 规则以及在编译期间让编译器状态警告/错误的任何技术?
  • 规则意味着将有符号的正整数转换为相同宽度的无符号整数不是问题。将负有符号整数转换为相同宽度的无符号整数与添加 pow(2, width in bits) 相同。
  • 我认为 -Wall -Wconversion -Wsign-conversion 解决了这个问题 - 感谢领导
【解决方案2】:

我不知道提供这种标志的编译器(尽管我总是可能错过了一个)。

如果没有它,您可以构建一个小模板,至少在一些明显的情况下,这种隐式转换是不可能的:

#include <cstdint>
#include <iostream>

using ::std::int32_t;
using ::std::uint32_t;

template <class T>
class holder {
    T value;
public:
    holder(T value) : value(value) {}
    operator T&() { return value; }
    operator T() const { return value; }
    holder &operator=(holder const &other) { value = other.value; return *this; }
};

int main(int argc, char *argv[]) {
    holder<int32_t> x = 9;

    holder<uint32_t> i = x;

    ++i;

    std::cout << " " << x << " " << i << "\n";
}

尝试用 g++ 编译给出:

trash9.cpp:20:23: error: conversion from 'holder<int>' to non-scalar type 'holder<unsigned int>' requested
  holder<uint32_t> i = x;
                       ^

但是,如果我们将第二个更改为 holder&lt;int32_t&gt; i = x;,则一切正常并按预期运行。

这足以满足您提供的演示代码,但并非在所有情况下都有效。特别是,仍然允许在计算表达式的过程中进行隐式转换:

void use(holder<uint32_t> v) {
    std::cout << v;
}

int main(int argc, char *argv[]) {
    holder<int32_t> x = 9;

    holder<int32_t> i = x;

    use(i | 1u);
}

如果您也想在这种情况下阻止转换,您可以这样做,但这需要做更多的工作——您需要从上面的代码中删除 operator Toperator T&amp; ,然后实现您想要支持的所有运算符。这会/可能会很乏味,至少会有点痛苦,但无论如何你可能会觉得它可以接受。

【讨论】:

  • 感谢您的信息 - 模板版本是否也可以解决将 int32_t 返回到 uint32_t 变量的函数? uint32_t x = fn(..) 返回 int32_t
  • 如果你使用holder&lt;uint32_t&gt; x = fn(...); 并且fn 被定义为返回一个int32_t,那么是的,代码将被拒绝(即不会编译)。
  • 我认为 -Wall -Wconversion -Wsign-conversion 解决了这个问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-24
  • 1970-01-01
  • 1970-01-01
  • 2012-12-01
  • 2011-07-15
  • 1970-01-01
  • 2023-03-03
相关资源
最近更新 更多