std :: valarray的运算符*有什么问题? [英] What's wrong with std::valarray's operator*?

查看:116
本文介绍了std :: valarray的运算符*有什么问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下MCVE,其中有两个值数组,其中w是两倍v( try在这里):

Consider the following MCVE, where I have two value arrays where w is two times v (try it out here):

#include <valarray>

using namespace std;

int main() {
  valarray<int> v { 1, 2, 3 };

  for ([[maybe_unused]] auto x : v) {} // Ok

  auto w = v * 2;     // Leads to failure in loop below
  //valarray<int> w = v * 2; // Works
  //auto w = v*=2;      // Works
  //auto w = v; w *= 2; // Works

  for ([[maybe_unused]] auto x : w) {} // Failure here
}

此示例无法在最后一个循环中使用clang和gcc编译(此处为gcc输出):

This example fails to compile with clang and gcc at the last loop with (gcc output here):

error: no matching function for call to 'begin(std::_Expr<std::__detail::_BinClos<std::__multiplies, std::_ValArray, std::_Constant, int, int>, int>&)'

问题的根源似乎是v * 2的递减类型(我认为由于显式地记录了该类型是可行的,因此似乎正在进行一些隐式转换).

The source of the problem seems to be the decuced type of v * 2 (I assume that because explicitly writing down the type works, so some implicit conversion seems to be taking place).

查看参考说明operator*可能返回与std::valarray<T>不同的内容. 我不了解其原因,但更令人困惑的是,相同似乎适用于operator*= ,除了我的auto作业在这里起作用.我希望operator*=operator*的返回值在这里是相同的(减去引用).

Looking at the reference notes, it seems that operator* may return something different than std::valarray<T>. I don't understand the reason for this but more puzzling is that the same seem to apply to operator*=, except that here my auto assignment works. I would expect the return values of operator*= and operator* to be the same here (delta the reference).

所以我的问题是:

  • Is this an implementation issue/bug? Or am I missing something?
  • What's the rationale behind the reference notes (e.g. why can the operators return something different that may not work with std::begin/std::end)?

(注意:我标记了c ++ 11这个问题,但似乎也适用于所有版本,最高为17)

推荐答案

有一个技巧叫表达式模板,它可以提高复合表达式的效率,但是使用auto会令人发指.

There is a trick called expression templates that permit efficiencies in compound expressions, but break horribly with use of auto.

更改此:

auto w = v * 2;

对此:

std::valarray<int> w = v * 2;

您的代码有效.

要了解为什么要使用表达式模板,请尝试以下操作:

To see why we want to use expression templates, try this:

std::valarray<int> a={1,2,3},b{4,5,6},c={2,4,8};
std::valarray<int> r = (a+b*2)*c;

此处,表达式模板避免创建临时的valarray a+b*2b*2,而是向下传递整个表达式,并使用逐个元素的操作构造r.

here the expression templates avoid creating a temporary valarray a+b*2 or b*2, but instead pass the entire expression down, and construct r with element-wise operations.

(a+b*2)*c中没有创建三元素valarray临时对象-只是一系列描述表达式结构和参数的对象.当将表达式赋给实际的valarray时,该表达式将在逐个元素的基础上求值.

No 3-element valarray temporaries are created in (a+b*2)*c -- just a series of objects that describe the expression structure and arguments. When assigned to an actual valarray the expression is then evaluated on an element-by-element basis.

但是auto不会转换为valarray;它只存储表达式模板对象.这样您的代码就会中断.

But auto doesn't convert to valarray; it just stores the expression template object. So your code breaks.

我不知道该标准的哪个版本允许这样做;不管怎样,一些valarray实现使用此方法,并且它增加了很多效率.没有它,valarray会很烂.

I don't know which versions of the standard permit this or not; regardless, some valarray implementations use this, and it adds a lot of efficiency. Without it, valarray frankly sucks.

这篇关于std :: valarray的运算符*有什么问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆