Можно ли изменить размер адаптера xarray вектора?

Увидев пример xtensor матричных адаптеров 1D-контейнеров, мне стало интересно, можно ли также иметь адаптер изменяемого размера для STL-контейнеров, таких как векторы.

В процессе хотелось бы еще и узнать и использовать тип такого адаптера, а не использовать auto.

Начиная с адаптера массива в стиле C и функции compute(), которая умножает вектор-строку 2x1 на столбец 2x1 и возвращает xarray в виде матрицы 2x2, я добрался до

#include <cstddef>
#include <xtensor/xarray.hpp>
#include <xtensor/xadapt.hpp>

template <class A>
void compute ( A& a ) {
    xt::xarray<double> b {1., 2.};
    b.reshape({2, 1});
    a = a * b; // size has changed, shape is now { 2, 2 }
}

int main() {
    std::size_t size = 2;

    ////////////////////////////////////////////////////////////////
    double* datavx = new double [ size ];
    
    for ( unsigned i = 0; i < size; i++ )
        datavx [ i ] = i;
    
    std::vector<std::size_t>   shapevx = { size };
    std::vector<std::size_t> stridesvx = { 1 };
    
    auto vx = xt::adapt ( datavx, size, xt::acquire_ownership(), shapevx, stridesvx );
    
    std::cout << "\nbefore reshape\n";
    for ( unsigned i = 0; i < size; i++ )
        std::cout << datavx [ i ] << " ";
    compute ( vx );
    std::cout << "\nafter reshape\n";
    for ( unsigned i = 0; i < size * size; i++ )
        std::cout << datavx [ i ] << " ";

    ////////////////////////////////////////////////////////////////
    std::vector<double> datav (size);
    for (unsigned i = 0; i < size; i++)
        datav[i] = i;

    std::vector<std::size_t> shapev = shapevx;
    std::vector<std::size_t> stridesv = stridesvx;

    using shape_type = std::vector<size_t>;
    using adaptor_typev = xt::xarray_adaptor<xt::xbuffer_adaptor<double*, xt::acquire_ownership>, xt::layout_type::dynamic, shape_type >;
    adaptor_typev my_adaptorv = xt::adapt(datav.data(), size, xt::acquire_ownership(), shapev, stridesv);
    std::cout << "\n";
    
    std::cout << "\nbefore reshape\n";
    for (unsigned i = 0; i < size; i++)
        std::cout << datav[i] << " ";
    compute(my_adaptorv);
    std::cout << "\nafter reshape\n";
    for (unsigned i = 0; i < size * size; i++)
        std::cout << datav[i] << " ";

    std::cout << std::endl;
    // prints 0 1 0 2

}

Результат, который я получаю от xarray_adaptor в стиле C (с веб-сайта xtensor) и std:vector xarray_adaptor соответственно:

before reshape
0 1
after reshape
0 1 0 2

before reshape
0 1
after reshape
0 1 nan -5.11336e-311

==== Program exited with exit code: 3221226356 ====
Time elapsed: 000:00.016 (MM:SS.MS)

Последние два значения предполагают, что изменения размера не произошло, а ненулевой код выхода показывает, что все не так. Если я запущу его в отладчике, он выйдет с SIGTRAP в конце main(). В верхней части стека вызовов написано ntdll!RtllsZeroMemory.

Означает ли это, что для изменения размера адаптера xarray для std::vector мне нужно отдельно изменить размер вектора? Или есть способ сделать это, не пытаясь стать владельцем данных вектора (начнем с того, что это звучит неправильно)?

xt::adapt(vdata.data(), vsize, xt::acquire_ownership(), ...) в конечном итоге приведет к неопределенному поведению путем двойного разрушения. Вы сообщаете адаптеру, что теперь он владеет данными и должен их удалить, но вектор vdata также считает, что данные принадлежат ему, и также удалит их.
Igor Tandetnik 25.05.2024 20:06

Во втором цикле vdata[i] демонстрирует неопределенное поведение путем доступа к индексу за пределами границ. vdata.size() по-прежнему равно 2, действительные индексы — 0 и 1.

Igor Tandetnik 25.05.2024 20:11

Покажите минимальный воспроизводимый пример, который фактически воспроизводит показанный результат. Вы говорите о «std:vector xarray_adaptor», но в вашем коде ничего подобного не появляется.

Igor Tandetnik 25.05.2024 20:15

В вашем минимальном воспроизводимом примере отсутствует определение функции compute() (она не является частью библиотеки xtensor). Код в вопросах должен быть самодостаточным, не полагаясь на внешние ссылки (не говоря уже о том, что в этой ссылке есть три функции compute(), что заставляет нас вручную устранять перегрузку).

JaMiT 25.05.2024 20:31

«Начиная с адаптера массива C-стиля» — Почему? Если вы перейдете по своей ссылке, а затем прокрутите вверх (та же страница), там будет «Адаптация std::vector». Почему бы вам не начать с «Адаптации std::vector», если ваша цель — адаптировать std::vector?

JaMiT 25.05.2024 20:33

Извините @IgorTandetnik, пример теперь полная программа. Итак, двойное удаление (одно из адаптера и одно из вектора) приводит к сбою программы? Еще один момент, который вы отмечаете по поводу того, что resize() не происходит, заключается в том, что право собственности на вектор не меняется?

alle_meije 26.05.2024 23:18

Спасибо @JaMiT — код «Адаптация std::vector», безусловно, самый простой, но две вещи, которые я упоминаю в своем посте: использование указанного типа, а не автора, и изменение размера контейнера после адаптации, не входят в этот пример.

alle_meije 26.05.2024 23:30

Как я уже сказал, вы используете адаптер для массивов в стиле C для адаптации необработанных данных, управляемых вектором. И вы сообщаете этому адаптеру, что он должен стать владельцем данных, в то время как вектор также владеет теми же данными. Вектор понятия не имеет, что вы вытаскиваете его данные прямо из-под его ног. Часть кода, которая касается datav и my_adaptorv, имеет множество неопределенного поведения. Посмотрите, изменится ли результат, если вы это сделаете auto my_adaptorv = xt::adapt(datav, shapev, stridesv);

Igor Tandetnik 27.05.2024 02:59
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
8
79
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Комментарии @JaMit и @IgorTandetnik помогли мне в правильном направлении - мне действительно нужен был адаптер вектора, а не массива в стиле C.

Но во всех примерах с векторными адаптерами использовались объявления auto, и мне все равно хотелось узнать тип адаптера.

старый ответ на StackOverflow позволил мне объединить эти два варианта: этот фрагмент кода показывает тип адаптера, который я затем использовал для объявления «вручную».

Другие вопросы по теме