在for循环的范围中,std::valarray的范围表达式无效

Invalid range expression of std::valarray in range for loop

本文关键字:范围 无效 valarray 表达式 std for 循环      更新时间:2023-10-16

我有一个简单的使用遍历临时std::valarray表达式在范围for循环,但得到 error:无效的范围表达式…

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<T>,因此理论上表达式的值应该是valarray<T>类型的临时实例。

简介:

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

版本: Apple LLVM Version 8.0.0 (clang800.0.38)目标:x86_64-apple-darwin15.6.0

注意下一行工作

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

作为"开始"answers"结束"可用于operator+返回类型,即valarray<T>,我想说错误是错误的,它应该编译。

你想做什么?如果你想遍历xxx,只在其中执行for语句:

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

但是回答你的问题的基本问题,表达式(xxx + yyy)是不可迭代的。如果你想在两个语句中都执行for循环,你需要执行两个for:

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 from edit: line

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

之所以有效,是因为它先进行追加操作,然后再进行迭代。和我上一个建议是一样的。但是(xxx+yyy)是不可迭代的。

从你的评论:valarray::operator+(valarray)不存在。valarray::operator+=(valarray)不存在

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

可移植的语法是
for(auto x : std::valarray<int>(xxx + zzz))

这在cppreference和26.7.1[valarray.syn]p4.1

标准中有说明

这是一个非常好的问题。原因是A+B对值数组的行为。

让我们看看这是什么意思。

首先,试试这些行:

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循环迭代。

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