шаблон специализации auto_ptr <T> - PullRequest
3 голосов
/ 07 апреля 2010

Может быть, я слишком усложняю вещи, но опять же, я делаю что-то вроде чистых интерфейсов. Допустим, я хочу специализацию auto_ptr для fstream - я хочу fstream по умолчанию для общего случая, но разрешить указатель замены?

 template <> 
 class auto_ptr<fstream> {
     static fstream myfStream; 
     fstream* ptr; 

 public: 
     auto_ptr() { 
         // set ptr to &myfStream;
     }
     reset(fstream* newPtr) {
         // free old ptr if not the static one. 
         ptr = newPtr 
     };
  } 

Считаете ли вы что-то другое или более элегантное? И как бы вы не допустили, чтобы что-то подобное выше распространялось за пределами этого конкретного модуля компиляции?

[Фактическим шаблоном является повышение :: scoped_ptr.]

РЕДАКТИРОВАТЬ:

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

class UserClass { 
public:
    auto_ptr<fstream> ptr; 
    UserClass() {  }
} 

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

Ответы [ 3 ]

2 голосов
/ 17 апреля 2010

Это не будет хорошо. Самая большая проблема состоит в том, что std :: auto_ptr удаляет базовый объект в его деструкторе. Это означает, что ваш параметр по умолчанию не может быть статическим. Единственный выбор, который вы можете сделать, - это сделать много хаков там, и, ИМХО, цена, которую вы заплатите, сохраняя весь этот дрянной код, не стоит того небольшого преимущества, которое у вас было бы.

1 голос
/ 17 апреля 2010

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

Boost определяет определенные функции для построения auto_ptr. Если вы переопределите это каким-либо образом, вы нарушили их спецификацию.

Придумайте имя для вашей новой функциональности, сделайте ее заводской функцией и не беспокойтесь о том, чтобы специализировать чужой шаблон.

РЕДАКТИРОВАТЬ: наследование от auto_ptr является еще одним вариантом, если вы действительно настроены на изменение семантики инициализации:

tempate < class T, T *d > 
struct defaulted_auto_ptr
    : public auto_ptr< T > {
    defaulted_auto_ptr( T *p = d ) throw() : auto_ptr<T>( p ) {} // set default
    defaulted_auto_ptr( auto_ptr<T> &r ) throw()
        : auto_ptr<T>( r ) {} // allow conversion
    template< class O > defaulted_auto_ptr( auto_ptr<O> &r ) throw()
        : auto_ptr<T>( r ) {}
};

fstream default_file;
typedef defaulted_auto_ptr< fstream, &default_file > file_ptr;

auto_ptr< fstream > baseptr = file_ptr(); // can assign to auto_ptr, but unsafe

Я немного сомневаюсь в компромиссе между затратами и выгодой, но это лучше, чем полное переосмысление auto_ptr.

Вы все еще должны выяснить, что делать, если дефолтный объект уничтожен. default_file выше будет delete d, потенциально много раз.

1 голос
/ 17 апреля 2010

Это выглядит разумно для меня, может сбить с толку, если его использование широко распространено в кодовой базе и не документировано.

Я замечаю, что вы осторожны, но я все равно подчеркну: убедитесь, что вы не освобождаете свой статический объект в два раза!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...