【问题标题】:Is unpacking variadic using array(or initializer_list) trick optimize-safe?使用数组(或 initializer_list)技巧优化安全解包可变参数吗?
【发布时间】:2021-03-29 04:41:36
【问题描述】:

由于 C++14 不能使用折叠表达式,为了使函数在每个可变参数上调用 bar,必须使用函数重载。

template<typename Arg>
void foo(Arg arg) {
  bar(arg);
}

template<typename Arg, typename ...Args>
void foo(Arg arg, Args... args) {
  bar(arg);
  foo(args...);
}

但是使用逗号运算符和括号中的括号,可以在不重载的情况下解包。

template<typename ...Args>
void foo(Args... args) {
  int dummy[] = {
    (bar(args), 0)...
  };
}

它按预期运行良好,但我的编译器总是警告我 dummy 未使用。 所以我担心编译器会删除dummy(因为它没有被使用并且实际上只由文字初始化),导致不调用bar
或者仅仅将dummy 声明为volatile 就足以保证bar 被调用?
我知道有 [[maybe_unused]] 属性,但它也是 C++17 的特性。

【问题讨论】:

  • 什么是“优化安全”?您是否担心优化会删除未使用的部分并由此改变代码的行为?
  • @largest_prime_is_463035818 是的,我担心编译器是否会删除 dummy 并导致不调用 bar

标签: c++ optimization c++14 variadic argument-unpacking


【解决方案1】:

所以我担心编译器会删除dummy(因为它没有被使用并且实际上仅由文字初始化),并导致不调用bar

编译器可能会删除dummy,但不能删除有副作用的bar调用(对于递归版本)。

所以你是安全的。

或者只是将dummy 声明为volatile"

那是最糟糕的。当你强制写入时。您以错误的方式删除了警告。

我知道有 [[maybe_unused]] 属性,但它也是 C++17 的特性。

转换为 void 是以前删除警告的常用方法。

【讨论】:

    【解决方案2】:

    不用担心,编译器优化不会破坏代码行为,否则编译器会被破坏,但是有复制省略等会以文档化的方式改变行为。

    在您的情况下,将评估调用并丢弃存储在数组中的返回值。因为这是您的意图,您可以通过使用变量来消除此警告!

    ((void)dummy);

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-24
      • 1970-01-01
      • 2010-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多