gpt4 book ai didi

c++ - 为什么在模板函数中将两个 xtensor 表达式加在一起会错误地广播?

转载 作者:行者123 更新时间:2023-11-28 01:30:51 33 4
gpt4 key购买 nike

考虑以下程序:

#include <iostream>
#include "xtensor/xarray.hpp"
#include "xtensor/xio.hpp"
#include "xtensor/xview.hpp"
xt::xarray<double> arr1
{1.0, 2.0, 3.0};

xt::xarray<double> arr2
{5.0, 6.0, 7.0};

template <typename T, typename U>
struct container{
container(const T& t, const U& u) : a(t), b(u) {}
T a;
U b;
};

template <typename T, typename U>
container<T, U> make_container(const T& t, const U& u){
return container<T,U>(t, u);
}

auto c = make_container(arr1, arr1);
std::cout << (arr1 * arr1) + arr2;

template <typename A, typename B, typename R>
auto operator+(const container<A, B>& e1, const R& e2){
return (e1.a * e1.b) + e2;
}

std::cout << (c + arr2);

如果我们看一下代码:

std::cout << (arr1 * arr1) + arr2;

它会输出:

{  6.,  10.,  16.}

然而,运行最后一行:

std::cout << (c + arr2);

产生以下内容:

{{  6.,   9.,  14.}, {  7.,  10.,  15.}, {  8.,  11.,  16.}}

为什么会这样?我更改了 operator+ 的函数定义到以下内容:

template <typename A, typename B, typename R>
auto operator+(const container<A, B>& e1, const R& e2){
std::cout << __PRETTY_FUNCTION__ << std::endl;
return (e1.b * e1.alpha) + e2;
}

输出有点令人惊讶:

auto operator+(const container<A, B> &, const R &) [A = xt::xarray_container<xt::uvector<double, std::allocator<double> >, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::xtensor_expression_tag>, B = xt::xarray_container<xt::uvector<double, std::allocator<double> >, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::xtensor_expression_tag>, R = double]
auto operator+(const container<A, B> &, const R &) [A = xt::xarray_container<xt::uvector<double, std::allocator<double> >, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::xtensor_expression_tag>, B = xt::xarray_container<xt::uvector<double, std::allocator<double> >, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::xtensor_expression_tag>, R = double]
auto operator+(const container<A, B> &, const R &) [A = xt::xarray_container<xt::uvector<double, std::allocator<double> >, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::xtensor_expression_tag>, B = xt::xarray_container<xt::uvector<double, std::allocator<double> >, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::xtensor_expression_tag>, R = double]
{{ 6., 9., 14.}, { 7., 10., 15.}, { 8., 11., 16.}}

为什么有 3 +在单个操作中调用的操作?是否在某处定义了导致此行为的宏? R输入 operator+给我们double ,实际上应该是 xt::xarray<double> .

如有任何见解,我们将不胜感激。

最佳答案

operator+在命名空间 xt 中定义采用通用引用,因此在编写 c + arr2 时比重载更受欢迎.

因此最后一行将返回 xfunction谁的第一个操作数是你的 container , 第二个是 xarray .

现在,自 container不是 xexpression , 在 xfunction 里面它被处理为... xscalar<container> !

因此,当您尝试访问此 xfunction 的第 i 个元素时,执行以下操作:xscalar<container> + arr2[i] (广播 xscalar)。自 xscalar<container>可转换为 container , 你的 operator+R 调用重载解析为 value_typearr2 , 即 double .

下面的循环说明了这种行为:

auto f = c + arr2;
for(auto iter = f.begin(); iter != f.end(); ++iter)
{
std::cout << *iter << std::endl;
}

它会生成以下对您的 operator+ 的调用:

operator+(c, arr[0]);
operator+(c, arr[1]);
operator+(c, arr[2]);

这就是为什么您看到 operator+ 有 3 次调用的原因.

关于c++ - 为什么在模板函数中将两个 xtensor 表达式加在一起会错误地广播?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51567370/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com