Явно выберите назначение копии

В С++ 11, если доступны как копирование, так и перенос, компилятор автоматически выбирает назначение копирования, если аргумент равен lvalue и присваивает переключение, если он является rvalue. Используя std::move можно явно выбрать назначение перемещения для lvalue. Но как можно явно выбрать назначение копии для rvalue?

Пример кода:

#include <iostream>

class testClass
{
public:
    testClass &operator=(const int &other) {
        std::cout << "Copy assignment chosen." << std::endl;
        return *this;
    }

    testClass &operator=(int &&other) {
        std::cout << "Move assignment chosen." << std::endl;
        return *this;
    }   
};  

int main(int argc, char *argv[])
{
    int a = 4;
    testClass test;

    test = a; // Selects copy assignment
    test = 3; // Selects move assignment

    test = std::move(a); // Selects move assignment
//  test = std::copy(3); // <--- This does not work

    return 0;
}

Ответ 1

Один из возможных способов - написать свою собственную copy чтобы привязать объект к ссылке lvalue:

template <class T>
constexpr T& copy(T&& t) noexcept
{
    return t;
}

И вы можете проверить это так:

test = copy(a);
test = copy(3);
test = copy(std::move(a));

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


Чтобы устранить страх перед пожизненной проблемой, рассмотрим некоторые соображения:

  • Эта функция copy принимает ссылку и немедленно возвращает ту же ссылку. Это означает, что вызывающий абонент отвечает за управление временем жизни.
  • Срок службы временного объекта сохраняется до конца заявления. Это приводит к тому, что объект остается достаточно длинным, чтобы его передавали в левую сторону =.

Ответ 2

Вы можете static_cast для const int&:

test = static_cast<const int&>(3);