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

不同行为的MSVC和clang为if Conconexpr分支

赖翰
2023-03-14

考虑到这个辅助函数:

template<typename Type>
std::string toString(Type const& value, bool encloseInQuotes = false) {
  if constexpr (std::is_same<bool, Type>::value) {
    auto s = value ? "true" : "false";
    return encloseInQuotes ? "\""s + s + "\"" : s;
  }

  if constexpr (std::is_arithmetic<Type>::value) {
    if (std::isnan(value)) {
      return encloseInQuotes ? "\"NaN\"" : "NaN";
    }
  }

  return "";
}

它应该将基本类型(和字符串)转换为字符串表达式,当我像这样使用它时,MSVC会出现编译错误:

int main() {
  std::string temp = toString(true);
  return 0;
}

有了clang,编译起来没有任何问题,但有了MSVC,我明白了:

2.

2.

2.

2.

2.

2.

2.

2.

2.

2.

2.

2.

2.

2.

2.

显然,编译器会考虑if constexpr(std::is_算术

如何在Windows上正确编译?


共有2个答案

微生曾琪
2023-03-14

std::isnanstd::isinf看似在MSVC中内部调用fp分类。该函数对于浮点类型重载,并且您传递bool类型的参数,因此调用是不明确的。

为了避免这种情况,您可以将参数强制转换为double

if constexpr (std::is_arithmetic<Type>::value) {
  if (std::isinf((double)value)) {
    return encloseInQuotes ? "\"INF\"" : "INF";
  }

  if (std::isnan((double)value)) {
    return encloseInQuotes ? "\"NaN\"" : "NaN";
  }

现场演示:https://godbolt.org/z/W7Z3r3

更新

这似乎是MSVC实现中的一个错误,因为根据cppreference,整型参数应该有一个重载,其行为与double重载相同。最简单的例子:

auto b = std::isnan(1);

现场演示:https://godbolt.org/z/qcTfQs

刘浩思
2023-03-14
匿名用户

对于bool至少有两种类型特征返回true

std::is_same<bool, Type>::value
std::is_arithmetic<Type>::value

然后打电话给std::isnan(true)。如果,请使用

if constexpr (std::is_same<bool, Type>::value) {
    auto s = value ? "true" : "false";
    return encloseInQuotes ? "\""s + s + "\"" : s;
}
else if constexpr (std::is_arithmetic<Type>::value) {
    if (std::isnan(value)) {
        return encloseInQuotes ? "\"NaN\"" : "NaN";
    }
    ...
}
else
    return "";

 类似资料:
  • 我试图使用clang和gcc交叉编译一个项目,但在使用时,我发现了一些奇怪的差异,例如。 现在,当涉及NAN时,我期望类型行为,但clang和gcc给出不同的结果: 当我使用它时,_mm_max_ps做了预期的事情。我尝试过使用,,但似乎没有效果。有什么想法可以让编译器之间的行为相似吗? 这里是锁销连接

  • GCC接受以下代码: 但是clang拒绝它并带有以下错误: 这似乎表明GCC和clang在重载解析期间执行某些操作的顺序有所不同。GCC似乎在尝试实例化模板候选者的返回类型之前抛弃了模板候选者,因为第二个参数(vs.)中的类型不匹配,而clang似乎反过来做。 谁是对的? 我相信这个问题对模板库的作者有着重要的意义。具体来说,如果clang是正确的,那么模板的作者将不得不做额外的工作,将错误转化为

  • 我正在定义一个类的构造函数,该构造函数约束检查传入迭代器的基础类型与类中定义的node_type的类型等价性,并借助概念或SFINAE。 但是,尝试了一些与

  • 这与为什么GCC不能为两个int32s的结构生成最优运算符==有关?。我在godbolt.org玩弄那个问题的代码,注意到了这个奇怪的行为。 https://godbolt.org/z/e49h6d 对于非零ptr,clang-O3(所有版本)生成此代码或类似代码: 这严格实现了C函数的短路行为,仅当x字段为零时加载y字段。 对于非零参考,clang 3.6和更早版本生成与非零ptr相同的代码,但

  • 问题内容: 考虑以下代码: 然后考虑一下: 为什么这两个有区别? (是的,我尝试搜索此内容)。 问题答案: 更改列表,然后返回一个 新 列表,如所示。 第一次尝试调用的表达式,如果失败,将在赋值之后调用(请参见Sven的评论进行较小的更正)。从那时起,它就完成了这一点’o突变魔术。

  • 我在下面添加可运行的代码段。第一个是React.PureComponent版本 为什么第二个成功运行,但第一个没有??我试图寻找原因,但没有找到任何好的理由