【问题标题】:Invalid range expression of std::valarray in range for loop循环范围内 std::valarray 的无效范围表达式
【发布时间】:2016-11-11 09:50:07
【问题描述】:

我有一个简单的用法,即在 for 循环范围内遍历临时 std::valarray 表达式,但得到 error: invalid range expression ...

main.cpp

#include <iostream>
#include <valarray>

int main()
{

    std::valarray<int> xxx {2,7,1,8,2,8};
    std::valarray<int> zzz {xxx};

    for (auto x : xxx + zzz) std::cout << x << std::endl;

    return 0;
}

clang++ main.cpp -std=c++11

main.cpp:10:17: error: invalid range expression of type 'std::__1::__val_expr<std::__1::_BinaryOp<std::__1::plus<int>, std::__1::valarray<int>, std::__1::valarray<int> > >'; no viable 'begin' function available
    for (auto x : xxx + zzz) std::cout << x << std::endl;
                ^ ~~~

它没有按我预期的那样编译真的有充分的理由吗? 重载的operator+的返回类型是valarray&lt;T&gt;,所以理论上表达式的值应该是valarray&lt;T&gt;类型的临时实例。

简介:

template<class T> valarray<T> operator+ (const valarray<T>& x, const valarray<T>& y);

版本: Apple LLVM 版本 8.0.0 (clang-800.0.38) 目标:x86_64-apple-darwin15.6.0

注意以下行作品

for (auto x : xxx += zzz) std::cout << x << std::end;

【问题讨论】:

标签: c++ c++11 foreach std valarray


【解决方案1】:

operator+ 返回类型可以使用“开始”和“结束”,即valarray&lt;T&gt; 我会说错误是错误的,它应该编译。

【讨论】:

  • 由于某些原因 gcc 和 clang 都返回 std::_Expr&lt;std::_BinClos&lt;std::__plus, _ValArray, _ValArray, int, int&gt;, int&gt; 而不是 std::valarray&lt;int&gt;
  • 这就是我问的原因......vc++可以做到。
  • valarrays的operator+的返回类型不需要是std::valarray(我什至会说如果是std::valarray,实现就坏了)
  • 不需要吗?破碎的?为什么?你能更好地解释一下吗?因为如果你看声明,你会发现它确实是 st​​d::valarray template&lt;class T&gt; valarray&lt;T&gt; operator+ (const valarray&lt;T&gt;&amp; x, const valarray&lt;T&gt;&amp; y);
【解决方案2】:

你想做什么? 如果你想遍历 xxx 在里面做 for only:

for (const auto x : xxx) std::cout << x << std::endl;

但回答您问题的基础知识,表达式 (xxx + yyy) 是不可迭代的。如果你想在两者中都执行 for 循环,则执行两个 fors:

for (auto x : xxx) std::cout << x << std::endl;
for (auto x : zzz) std::cout << x << std::endl;

如果你想在一个循环中完成,你可以追加两个

xxx += yyy;
for (auto x : xxx) std::cout << x << std::endl;

来自编辑的PD:行

for (auto x : xxx += yyy) std::cout << x << std::endl;

之所以有效,是因为它先进行追加,然后进行迭代。相当于我最后的建议。但是 (xxx+yyy) 是不可迭代的。

根据您的评论: valarray::operator+(valarray) 不存在。 valarray::operator+=(valarray) 确实存在。

【讨论】:

  • "表达式 (xxx + yyy) 无法说出" -- 为什么?
  • @LanceLi xxx+yyy 的结果是不可迭代的。运算符 + 与运算符 += 不同。
  • 看看en.cppreference.com/w/cpp/numeric/valarray 运算符,例如 + 在每个元素的基础上执行操作,而 += 正在附加数组。
【解决方案3】:

for循环的范围使用非成员std::begin和std::end,对于std::valarray的operator+的返回类型,它们不需要存在。

可移植语法是

for(auto x : std::valarray<int>(xxx + zzz))

这在cppreference 和 26.7.1[valarray.syn]p4.1 下的标准中注明

【讨论】:

    【解决方案4】:

    这是一个非常好的问题。原因是 A+B 在 valarrays 上的行为。

    让我们看看我的意思。

    首先,试试这些行。

    std::valarray<int> xxx {2,7,1,8,2,8};
    std::valarray<int> zzz {xxx};
    auto t=xxx+zzz;
    cout<<typeid(t).name()<<endl;
    cout<<typeid(xxx).name()<<endl;
    cout<<typeid(xxx+zzz).name()<<endl;
    

    你会注意到它们不一样,这是由于这里定义了 + 运算符https://en.cppreference.com/w/cpp/numeric/valarray/operator_arith3 正如它所写的那样,类型是推断出来的。这意味着它的行为类似于 auto。那么问题是为什么它不推导出相同的类型 valarray。可能是因为编译器优化特性,也可能是一个错误,但很明显,引用并没有强制编译器推导出相同的类型。问题是推导的类型恰好不能被基于范围的 for 循环迭代。

    如果有什么不清楚的地方请告诉我。

    【讨论】:

      猜你喜欢
      • 2012-03-30
      • 2014-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-23
      • 1970-01-01
      • 2016-05-06
      • 2014-04-07
      相关资源
      最近更新 更多