【问题标题】:Scope of variables declared inside `if constexpr` blocks`if constexpr` 块中声明的变量范围
【发布时间】:2017-10-23 00:49:54
【问题描述】:

这是格式错误还是只是编译器(在我的情况下为 g++-7)仍然存在错误?因为它说n 没有定义。

template<class T>
auto tup(T const& t)
{
    if constexpr(hana::length(t)() % 2)
        auto n = hana::append(t, nullptr);
    else
        auto const& n = t;

    return n;
}

int main()
{
   std::cout << hana::length(tup(std::tuple(3, "h", 'c'))) << '\n';
}

n 将始终被定义,无论编译器将转到哪个分支。

【问题讨论】:

  • 如果if constexpr 的作用域规则与if 语句的标准作用域规则相匹配,则此错误是有意义的,因为变量声明的作用域仅限于if 或@ 的主体987654327@。但我不知道if constexpr 应该如何工作,因此不知道这是否应该发生。
  • 格式不正确。如果那些auto 声明甚至被编译,我会感到惊讶,除非周围有{...} 块,但无论如何,变量会随着它们的范围消失,它们在else; 之前终止于@987654333分别@声明,
  • 请注意,您可以只使用两个 return 语句。废弃的return 语句不影响对占位符返回类型的推导。
  • @Peregring-lk 当然不是。我不知道你从哪里得到这个想法。它是一种编译语言,而不是剪贴板。
  • 如果if constexpr() 允许在模板化方法或函数中使用局部变量的替代声明,那将是很好的,这取决于传入的类型。如:if constexpr(std::is_same_v&lt;T,short&gt;) typedef int intermediate; else typedef long long intermediate; 所以如果 T 是 int,intermediate 将会是 long long,但如果 T 是 short,intermediate 会是 int。当然,这可以通过辅助模板结构轻松实现,但如果可以避免这些结构,那就太好了。

标签: c++ scope c++17 constexpr


【解决方案1】:

您的程序格式错误,因为每个n 都被限制在声明它的单个语句的范围内。

C++17 草案 N4659 [stmt.select]/1 说:

selection-statement 中的子语句(每个子语句,在if 语句的else 形式中)隐式定义了一个块范围([basic.scope])。如果选择语句中的子语句是单个语句而不是复合语句,就好像它被重写为包含原始子语句的复合语句。 [ 例子:

if (x)
  int i;

可以等效地改写为

if (x) {
  int i;
}

因此在if 语句之后,i 不再在范围内。 - 结束示例 ]

此规则适用于所有 forwhileswitchif 语句 - 无论 constexpr 关键字是否与 if 一起使用。

【讨论】:

  • 看到 C++ 标准委员会不明白为什么 constexpr 语句的范围规则必须与运行时范围规则不同,真的很糟糕。那么,这些规则的另一个关键字,嗯?
  • @Andry 你是说你想让事情变得不那么一致?如果在if 语句之后仅使用一个if constexpr 分支中声明的名称,会发生什么情况?
  • 我只想说编译时 if 表达式已被开发以首先替换 #if-#else-#endif,从预处理程序编程转移到 constexpr 过程编程,但不是他们增加了更多的歧义,并没有以简单的方式解决这个问题。为什么我们在这里需要另一个级别的复杂性,新的 C++ 不是已经重载了语法糖块,仔细一看只是一堆过度设计的结构吗?
【解决方案2】:

constexpr 在这种情况下不做任何更改。

和这个例子一模一样

int foo (int a)
 {
   if ( a == 0 )
    {
      int r = 0;
    }
   else
    {
      int r = 0;
    }

   return r;
 }

r 在这两种情况下都定义了。并且具有相同的值。

r的范围仅限于if,并没有到达return

如果能解决问题立即退货;我是说

template<class T>
auto tup(T const& t)
{
    if constexpr(hana::length(t)() % 2)
        return hana::append(t, nullptr);
    else
        return t;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-29
    • 2018-08-02
    • 2020-06-07
    • 2020-07-31
    • 2020-03-18
    • 2014-09-20
    • 1970-01-01
    • 2013-11-19
    相关资源
    最近更新 更多