and*_*eee 11 c++ operators language-lawyer c++11 valarray
考虑下面的MCVE,其中有两个值数组,其中w两次是两次v(在此处尝试):
#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
}
Run Code Online (Sandbox Code Playgroud)
这个例子在最后一个循环中用clang和gcc编译失败(这里是gcc输出):
error: no matching function for call to 'begin(std::_Expr<std::__detail::_BinClos<std::__multiplies, std::_ValArray, std::_Constant, int, int>, int>&)'
Run Code Online (Sandbox Code Playgroud)
问题的根源似乎是减少的类型v * 2(我假设因为显式地记录了该类型有效,所以似乎正在进行一些隐式转换)。
查看参考注释,似乎operator*返回的内容与std::valarray<T>。我不明白这样做的原因,但更令人困惑的是,这似乎适用于operator*=,除了我的auto作业在这里起作用。我期望的返回值operator*=,并operator*以相同这里(增量参考)。
所以我的问题是:
std::begin/的其他内容std::end)?(注意:我标记了这个问题c ++ 11,但它似乎也适用于所有版本,最高为17)
Yak*_*ont 13
有一个技巧叫表达式模板,可以提高复合表达式的效率,但是使用会严重破坏auto。
更改此:
auto w = v * 2;
Run Code Online (Sandbox Code Playgroud)
对此:
std::valarray<int> w = v * 2;
Run Code Online (Sandbox Code Playgroud)
并且您的代码有效。
要了解为什么我们要使用表达式模板,请尝试以下操作:
std::valarray<int> a={1,2,3},b{4,5,6},c={2,4,8};
std::valarray<int> r = (a+b*2)*c;
Run Code Online (Sandbox Code Playgroud)
在这里,表达式模板避免创建临时的valarray a+b*2或b*2,而是向下传递整个表达式,并r使用逐个元素的操作进行构造。
不会创建3元素的valarray临时(a+b*2)*c对象,而只是创建描述表达式结构和参数的一系列对象。当将其分配给实际valarray表达式时,将在逐个元素的基础上对表达式进行求值。
但是auto不会转换为valarray; 它只存储表达式模板对象。因此,您的代码会中断。
我不知道该标准的哪个版本允许这样做;不管怎样,某些valarray实现使用此方法,并且它增加了很多效率。没有它,valarray会很烂。
| 归档时间: |
|
| 查看次数: |
268 次 |
| 最近记录: |