C++ 为什么在模板函数中将两个xtensor表达式添加在一起会导致错误广播?

C++ 为什么在模板函数中将两个xtensor表达式添加在一起会导致错误广播?,c++,templates,xtensor,C++,Templates,Xtensor,考虑到以下方案: #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, type

考虑到以下方案:

#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 << (c + arr2);
为什么会这样?我将
操作符+
的函数定义更改为:

{{  6.,   9.,  14.}, {  7.,  10.,  15.}, {  8.,  11.,  16.}}
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;
}
模板
自动操作员+(常量容器和e1、常量R和e2){

std::cout在命名空间
xt
中定义的
运算符+
采用通用引用,因此在编写
c+arr2
时首选重载

因此,最后一行将返回一个
xfunction
,其第一个操作数是您的
容器
,第二个操作数是
xarray

现在,由于
container
不是
xexpression
,因此在
xfunction
中,它被当作一个
xscalar
处理

因此,当您尝试访问此
xfunction
的第i个元素时,将执行以下操作:
xscalar+arr2[i]
(播放
xscalar
)。由于
xscalar
可转换为
容器
,因此调用
操作符+
重载时,将
R
解析为
arr2
值类型
,即

以下循环说明了此行为:

auto f=c+arr2;
对于(自动iter=f.begin();iter!=f.end();++iter)
{

std::cout在命名空间
xt
中定义的
运算符+
采用通用引用,因此在编写
c+arr2
时首选重载

因此,最后一行将返回一个
xfunction
,其第一个操作数是您的
容器
,第二个操作数是
xarray

现在,由于
container
不是
xexpression
,因此在
xfunction
中,它被当作一个
xscalar
处理

因此,当您尝试访问此
xfunction
的第i个元素时,将执行以下操作:
xscalar+arr2[i]
(播放
xscalar
)。由于
xscalar
可转换为
容器
,因此调用
操作符+
重载时,将
R
解析为
arr2
值类型
,即

以下循环说明了此行为:

auto f=c+arr2;
对于(自动iter=f.begin();iter!=f.end();++iter)
{

std::cout Hi Johan,在这种情况下,你建议我如何重载
操作符+
?如果通用引用优先于每个操作,那么在包装类之上添加操作符可能非常困难。我还没有找到合适的模板匹配,到目前为止它具有适当的优先级。我认为
xtensor
应该d根据用户定义的某些模板专门化,提供一种方法来禁用自定义类型的运算符。我将就此提出一个问题。嗨,Johan,在这种情况下,你建议我如何重载
运算符+
?如果通用引用优先于每个操作,那么在上面添加运算符可能非常困难f包装类。到目前为止,我还没有找到一个合适的模板匹配,它将具有适当的优先级。我认为
xtensor
应该提供一种方法,根据用户定义的一些模板专门化,禁用自定义类型的运算符。我将为此提出一个问题。
{{  6.,   9.,  14.}, {  7.,  10.,  15.}, {  8.,  11.,  16.}}
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.}}