Почему добавление двух выражений 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, 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>,

Любые идеи будут оценены, спасибо.

0

Решение

operator+ определяется в пространстве имен xt принимает универсальные ссылки, и поэтому предпочтительнее вашей перегрузки, когда вы пишете c + arr2,

Таким образом, эта последняя строка вернет xfunction чей первый операнд твой containerи второй xarray,

Теперь, так как container это не xexpression, внутри xfunction это обрабатывается как … xscalar<container>!

Таким образом, когда вы пытаетесь получить доступ к i-му элементу этого xfunctionвыполняется следующая операция: xscalar<container> + arr2[i] ( xscalar транслируется). поскольку xscalar<container> конвертируется в container, ваш operator+ перегрузка вызывается с R решен как value_type из arr2, то есть, 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]);

Вот почему вы видите 3 звонка вашего operator+,

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]