【问题标题】:conditional operator bug in c++?C++中的条件运算符错误?
【发布时间】:2017-10-11 01:13:06
【问题描述】:

这些演示函数在 gcc 中不应该是无限循环 因为条件运算符应该只评估活动部分。

它们在 Visual Studio 2015 中正确编译,但在 g++ 6.3 中给出无限递归错误编译错误。我错过了什么?

template <int n>
constexpr int infinite_loop_error(){
   return (n)  ? infinite_loop_error<n - 1>() : 0;
}

template <int n> 
constexpr int infinite_loop_error_2(){
   if (n) return infinite_loop_error_2<n - 1>(); 
   else   return 0;
}

void main() {
  infinite_loop_error<3>();
  infinite_loop_error_2<3>();
}

【问题讨论】:

  • 标准中有没有说这不应该是无限递归?也许 C++17 中的 constexpr(我认为?)将是一个解决方案。
  • 我假设您知道可以通过创建函数模板的特化来解决问题。
  • 致凯文:是的! "if constexpr" 语句(用 clang 测试过)对此很有效。感谢您的建议

标签: c++ gcc conditional-operator


【解决方案1】:

这是 MSVC 中的一个错误,您的程序不应该编译。您正在混淆运行时递归和编译时递归。​​

虽然程序应该只在运行时评估三元表达式的一只手,但编译器仍然需要为三元表达式的两只手(以及if 条件的两个分支)生成代码)。您的程序在代码生成期间失败,因为编译器找不到可以停止的点。 MSVC “成功”了,因为它过早应用优化,违反了 as-if 规则。

您需要使用template specialization as a stopping condition:

template <int n>
constexpr int infinite_loop_error(){
   return (n)  ? infinite_loop_error<n - 1>() : 0;
}

template <>
constexpr int infinite_loop_error<0>(){
    return 0;
}

template <int n> 
constexpr int infinite_loop_error_2(){
   if (n) return infinite_loop_error_2<n - 1>(); 
   else   return 0;
}

template <> 
constexpr int infinite_loop_error_2<0>(){
   return 0;
}

int main() {
  infinite_loop_error<3>();
  infinite_loop_error_2<3>();
}

编译器不会从定义中实例化infinite_loop_error&lt;0&gt; 以使其进一步递归,而是使用您为其提供的定义并正确停止编译时递归。​​

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-12
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-21
    相关资源
    最近更新 更多