В чем причина ошибки компилятора «use of deleted function» в данном коде?

Привет!
Прошу пояснить причину ошибки в следующем коде:
// Класс создающий объекты и предоставляющий к ним доступ
template<typename T>
class Singleton
{
public:
    /*!
     * \brief Создание экземпляра класса
     */
    template<typename ... Args>
    inline static void create(Args ... arsg)
    {
        if (m_pInstance != nullptr)
            return;

        static T instance(arsg...);
        m_pInstance = &instance;
    }

    /*!
     * \brief Доступ к экземпляру класса по ссылке
     */
    inline static T& get()
    {
        assert(m_pInstance && "Singleton is not initialized!");
        return *m_pInstance;
    }

    Singleton() = delete;
    ~Singleton() = delete;
    
    Singleton(const Singleton&) = delete;
    Singleton& operator =(const Singleton&) = delete;

    Singleton(Singleton&&) = delete;
    Singleton& operator =(Singleton&&) = delete;

private:
    static T* m_pInstance;
};

template<typename T>
T* Singleton<T>::m_pInstance(nullptr);

Пытаюсь создать экземпляр класса с удаленными конструкторами копирования и перемещения:
// Класс
class MyClass
{
public:
MyClass(){}
MyClass(const MyClass&) = delete;
MyClass(MyClass&&) = delete;
};
//Код вызова
Singleton<MyClass>::create();

И получаю ошибку компилятора:
Singleton.h: In instantiation of ‘static void Singleton::create(Args ...) [with Args = {}; T = MyClass]’:
mycode.cpp:16:47: required from here
Singleton.h:34:34: error: use of deleted function ‘MyClass(MyClass&&)’
static T instance(arsg...);
^
In file included from mycode.cpp:6:0:
mycode.h:82:5: note: declared here
MyClass(MyClass&& orig) = delete;

Понимаю что компилятор хочет конструктор, но почему он его хочет? Подскажите где про это почитать
  • Вопрос задан
  • 3323 просмотра
Пригласить эксперта
Ответы на вопрос 1
@Ariox41
Просто замените круглые скобки на фигурные в списке инициализации: пример.

Пустой список аргументов не может быть передан в конструктор через круглые скобки - иначе это будет эквивалентно строке MyClass value(); - а это уже объявление функции. Из-за этого пустой список аргументов интерпретироваться как пустой список инициализации, но пустой список инициализации опять же нельзя передать в конструктор без аргументов, используя круглые скобки, т.к. один аргумент всё-таки есть. Но при использовании фигурных скобок список инициализации нормально вызывает конструктор без аргументов. При этом неявное преобразование из пустого списка инициализации в MyClass возможно - неявно вызывается конструктор без аргументов:
void foo(MyType2&&){ }
foo({}); // Компилируется

А значит строка MyClass({}) преобразует {} во временный объектMyClass, а его попытается передать в удалённый конструктор перемещения MyClass
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы