создание типа, который можно инициализировать с помощью присваивания, но нельзя скопировать

Я ищу, чтобы создать тип, который может быть инициализирован с присваиванием из другого типа, но не может быть скопирован. Идея аналогична идее интеллектуального указателя с заданной областью в том, что я хочу, чтобы объект этого типа владел ресурсом в течение его времени жизни, но я также хочу иметь возможность использовать синтаксис присваивания. Итак, в кратком изложении, это то, что я хочу:

T x = new U; // allowed
T y(new U);  // allowed
T z = x;     // not allowed
T x2(x)      // not allowed

Это то, что я пытался до сих пор …

#include <boost/noncopyable.hpp>

class U {};

class T : boost::noncopyable {
public:
T(U *p) : p_(p) {
}

~T() {
delete p_;
}

operator bool() const { return p_ != 0; }

private:
U *p_;
};

int main() {
T x = new U; // allowed
T y(new U);  // allowed
//T z = x;     // not allowed
//T x2(x)      // not allowed
}

что, к сожалению, приводит к ошибке:

$ g ++ test.cc -o test /usr/include/boost/noncopyable.hpp: в копии
конструктор ‘T :: T (const T&) ‘: /usr/include/boost/noncopyable.hpp:27:7:
ошибка: ‘boost :: noncopyable _ :: noncopyable :: noncopyable (const
повышение :: noncopyable _ :: noncopyable&) ‘является частным test.cc:6:30: ошибка:
в этом контексте test.cc: в функции ‘int main ()’: test.cc:20:12:
Примечание: синтезированный метод ‘T :: T (const T&) ‘сначала требуется здесь

ПРИМЕЧАНИЕ. Функции перемещения в C ++ 11 для меня неактивны, так как они должны быть скомпилированы с относительно старой версией gcc, которая не поддерживает C ++ 11.

Из-за отсутствия поддержки C ++ 11, я не уверен, что есть «хорошее» решение. Но я решил спросить.

2

Решение

Если мое понимание комментариев верно — вы хотите что-то подобное:

U* create_T() { return new U; }
if (T t = create_T())
{
// do something with t
}

Проблема здесь, уже упоминавшаяся в комментариях: это синтаксис T t = u просто вызывает конструктор копирования. Если ты типа T это эквивалентно: T t(u), Если uкак в вашем примере, имеет другой тип, преобразуемый в T (here by T::T(U*)) то на самом деле это так: T t(T(u)), Здесь у вас есть конструктор копирования, на который жалуется компилятор.

Там нет решения, потому что это не является действительным if синтаксис:

if (T i(create_T())) {}

Однако я не написал бы все это без хорошего совета;)

Вы можете забыть о проблемах с конструктором копирования следующим синтаксисом:

if (U* u = create_T()) {
T t(u);
....
}

КСТАТИ, std::auto_ptr имеет ту же проблему, что и ваш T тип. Просто добавьте явное к вашему T(U*) конструктор, и вы увидите сходство с auto_ptr:

class U {};

class T : boost::noncopyable {
public:
explicit T(U *p) : p_(p) {
}

~T() {
delete p_;
}

private:
U *p_;
};

int main() {
T x = new U; // allowed
T y(new U);  // allowed
std::auto_ptr<U> a = new U;
std::auto_ptr<U> b(new U);
}

Результаты в:

prog.cpp:25: error: conversion from ‘U*’ to non-scalar type ‘T’ requested
prog.cpp:27: error: conversion from ‘U*’ to non-scalar type ‘std::auto_ptr<U>’ requested

Вот мой ideone изучение…

1

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

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