1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/mirrors-iceoryx

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
move_and_copy_helper.md 6.9 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 30.11.2024 01:51 01c7879

Помощник для перемещения и копирования

Резюме и описание проблемы

В настоящее время некоторые классы в нашей кодовой базе используют оператор присваивания в конструкторе (ctor), чтобы избежать дублирования кода, как видно из проблемы №1517. Однако в проблеме №1686 отмечается, что самоприсваивание не должно происходить в ctor. Поэтому необходимо принять альтернативный подход, чтобы заменить текущую реализацию.

Один из методов включает размещение общего логического кода в отдельной функции, которая далее называется copy_and_move_impl. Эта функция затем вызывается в ctor и операциях присваивания с использованием параметров шаблона для указания метода инициализации члена.

Предпосылка

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

Терминология

  • MoveAndCopyOperations — класс перечисления, включающий:
    • CopyConstructor
    • MoveConstructor
    • CopyAssignment
    • MoveAssignment

Цели

Цель MoveAndCopyHelper:

  • позволить специальным конструкторам указывать источник вызова (например, CopyConstructor) при вызове copy_and_move_impl;
  • предоставить согласованный способ выражения обмена данными в copy_and_move_impl;
  • предложить способ игнорировать MoveAndCopyOperations и принудительно использовать ctor или присваивание, удовлетворяя потребности пользователей в особых обстоятельствах.

Дизайн

  • Предоставить класс перечисления MoveAndCopyOperations, чтобы описать ожидаемое поведение переменных-членов во время инициализации (например, используя копирование или перемещение). Передача этого перечисления в качестве параметра шаблона в copy_and_move_impl гарантирует, что специальные конструкторы вызываются должным образом.
  • Предоставить такие функции, как transfer, чтобы гарантировать, что процесс обмена переменными-членами соответствует MoveAndCopyOperations.

Сценарий

Transfer

В настоящее время существует три функции: transfer, create_new и assign. Описанные ниже сценарии кратко описывают подходящее использование каждой функции.

  • transfer: это универсальная функция для передачи данных. Рекомендуется использовать её в случаях, когда вы не имеете дело с потенциально неинициализированной памятью.
  • create_new: в некоторых случаях, особенно во время операций конструктора, некоторые члены класса являются ленивой инициализацией. Для этих членов необходимо использовать конструктор копирования или перемещения, даже если они доступны через оператор присваивания.
  • assign: TBD.

Пример кода

// header

#include "iox/move_and_copy_helper.hpp"

constexpr uint64_t CAPACITY {1024};

class Test
{
  public:
    Test();
    Test(const Test&);
    Test(Test&&);
    Test& operator=(const Test&);
    Test& operator=(Test&&);

    uint64_t size();

  private:
    int m_data[CAPACITY];
    uint64_t m_size{0};
}

// implementation
Test::Test(const Test& rhs)
{
    copy_and_move_impl<MoveAndCopyOperations::CopyConstructor>(rhs);
}

Test::Test(Test&& rhs)
{
     copy_and_move_impl<MoveAndCopyOperations::MoveConstructor>(rhs);
}

Test& Test::operator=(const Test& rhs)
{
    // you may do self-assignment check in copy_and_move_impl
    if (this != &rhs)
    {
        copy_and_move_impl<MoveAndCopyOperations::CopyAssignment>(rhs);
    }

    return *this;
}

Test& Test::operator=(Test&& rhs)
{
    // you may do self-assignment check in copy_and_move_impl
    if (this != &rhs)
    {
        copy_and_move_impl<MoveAndCopyOperations::MoveAssignment>(std::move(rhs));
    }
    return *this;
}

void Test::size()
{
    return m_size;
}

template <MoveAndCopyOperations Opt, typename RhsType>
void Test::copy_and_move_impl(RhsType&& rhs)
{
    // you can set alias to simplify code
``` ```
using Helper = MoveAndCopyHelper<Opt>;

// you can determine the current 'Opt' at compile time for compile-time branching decisions.
constexpr bool is_ctor = Helper::is_ctor;
constexpr bool is_move = Helper::is_move;

// self assignment check if needed
if constexpr (!is_ctor)
{
    if (this == &rhs)
    {
        return;
    }
}

// for ctor operation
if constexpr (is_ctor)
{
    // reset something if needed
    reset_something();
}

// transfer data example
for (uint64_t i = 0; i < rhs.size(); ++i)
{
    // @Recommended method
    Helper::transfer(m_data[i], Helper::move_or_copy(rhs.data[i]));

    // @Alternative method
    if constexpr (is_move)
    {
        Helper::transfer(m_dаta[i], std::move(rhs.dаta[i]));
    }
    else
    {
        Helper::transfer(m_data[i], rhs.data[i]);
    }
}

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/mirrors-iceoryx.git
git@api.gitlife.ru:oschina-mirror/mirrors-iceoryx.git
oschina-mirror
mirrors-iceoryx
mirrors-iceoryx
main