Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Задать поведение компилятора.  (Прочитано 7776 раз)
0 Пользователей и 1 Гость смотрят эту тему.
sss
Специалист

ru
Offline Offline

« : 03-07-2012 08:35 » 

Здравствуйте.

Есть код автобуфера
Код: (C++)
template <typename _T, AutoReleaseMode arm = armMemFree>
class auto_buf
{
protected:
   _T*                        m_ptr;
   mutable bool               m_fConst;

public:
  //-----------------------------------------------------------------------------
 explicit auto_buf( const _T* ptr) : m_ptr( const_cast<_T*>( ptr)), m_fConst( true)
 {
 };
  //-----------------------------------------------------------------------------
 explicit auto_buf( _T* ptr = NULL) : m_ptr( ptr), m_fConst( false)
 {
 };
 //-----------------------------------------------------------------------------
 ~auto_buf( )
 {
   free();
 }

С двумя конструкторами. Когда надо чтобы буфер не удалял при выходе из зоны видимости вызывается конструктор
(const _T*), когда надо чтобы удалял (_T*).
Теперь вот ситуация.

Код: (C++)
typedef  auto_buf<TCHAR>     tchar_a;

{
  TCHAR* p = (TCHAR*) 0xFEEDBABA;//не важно
  bool   fFlag = true; //не важно
  tchar_a b( fSome ? (TCHAR*) p : (const TCHAR*) p);
}

При любой ситуации вызывается конструктор const _T*.
Как мне поступить для исключения такого кода? Просто "не делай так"?
Или может кто-нибудь знает что можно придумать? Пусть он не компилируется
с какой нибудь ошибкой. Но как это сделать?
Атрибут explicit спокойно пропускается компилятором (BDS 2006).
« Последнее редактирование: 03-07-2012 08:37 от sss » Записан

while (8==8)
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 03-07-2012 09:22 » 

Насколько понимаю, здесь компилятор берёт два типа возвращаемого значения в ?: и выводит общий тип, оказывающийся константным.
Может, с копирующим конструктором сработает? В духе:
Код: (C++)
tchar_a b = fSome ? tchar_a(p) : tchar_a((const TCHAR*) p);
но пока не проверял.
Записан
sss
Специалист

ru
Offline Offline

« Ответ #2 : 03-07-2012 13:40 » 

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

Код: (C++)
auto_buf( _T* ptr, bool bConst)

Т.е. явное управление константным признаком..
Записан

while (8==8)
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 03-07-2012 13:45 » 

sss, тут, наверное, Александреску в помощь Улыбаюсь Думается, если подшаманить с шаблонным базовым типом, то можно на этапе компиляции создавать автобуфер с константным или не-константным содержимым, то есть, чтобы, условно, auto_buf<Type*> и auto_buf<const Type*> - это были два разных типа на этапе компиляции, и у каждого своя стратегия для деструктора.
По идее, должно быть реализуемо: нужно лишь сделать статический assert для проверки, что тип является указателем, а далее в конструктор принимать параметр Type, а не Type*.
« Последнее редактирование: 03-07-2012 13:47 от Вад » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #4 : 03-07-2012 16:33 » 

template <typename _T, AutoReleaseMode arm = armMemFree, bool bConst=true>

м ?
Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 03-07-2012 16:58 » 

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

По-хорошему, это 2 класса, реализующих единый интерфейс: один класс обеспечивает очистку буфера, другой - нет. И конечно, константность значения в общем случае не коррелирует с необходимостью очистки.

А ещё лучше отделить собственно буфер (как объект, сам выделяющий и освобождающий используемую память) от ссылки на буфер - вспомогательного объекта, дающего лишь точку доступа к буферу. Буфер заодно может считать ссылки или же управлять состоянием ссылок (valid, когда буфер жив, invalid, когда буфер уже уничтожен).

Чем-то похожую пару образуют коллекция и её итераторы.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
sss
Специалист

ru
Offline Offline

« Ответ #6 : 04-07-2012 01:19 » 


Единственное, чего я не понимаю, так это области применения такого типа. Выглядит он уж очень узкофункциональным.
...
Всё верно.
Моё личное убеждение - шаблонные классы могут применяться только как узкофункциональные объекты...
Естественно я показал не все методы класса. Там ещё оператор присваивания указателю на тип есть.
А применяется, например, в функциях в которых вызывающая сторона или предоставляет буфер или нет.
Например в потокобезопасной функции преобразования числа в строку..

Код: (C++)
char_a StrFromLongA( long val, char* buf, long radix)  throw ( ELowResources*, ESystemError*)
{
  char_a res ((const char*) buf);
  if ( buf == NULL)
    res = StrAllocA( STRDEF_CCH_FOR_LONG);
  Str32ToA((unsigned long) val, res, radix, ( radix == 10) && ( val < 0));
  return res;
}

Я нисколько не призываю всех делать также. Просто вдруг понял что есть вот такой "side effect"
без использования макросов и ни хотел бы случайно где нибудь допустить утечки.
Решил спросить - не знает ли кто как это сделать?

template <typename _T, AutoReleaseMode arm = armMemFree, bool bConst=true>

м ?

Не, так наверное не пойдет. Думаю возникнет та же коллизия но уже при инстацировании..
Да и вообще это уже слишком сложно для меня  Улыбаюсь Я лучше тогда заменю такой класс на класс
без шаблонов  С ума сойти....
« Последнее редактирование: 04-07-2012 01:28 от sss » Записан

while (8==8)
sss
Специалист

ru
Offline Offline

« Ответ #7 : 04-07-2012 01:38 » new


...
считать ссылки или же управлять состоянием ссылок
...

Сейчас перечитал пост в пятый раз и наконец то увидел эти строки.  А то после строк
"Выглядит он уж очень узкофункциональным."
даже дальше не читал получается  Улыбаюсь  - кинулся писать ответ.

Да именно также и я думаю!!! Этот код автобуфера написан лет 9 назад. В течении прошедшего
времени я давно уже перешел на подсчёт ссылок в управлении временем жизни объектов, а вот
этот код не трогал. Он работал да работал.
« Последнее редактирование: 04-07-2012 04:47 от sss » Записан

while (8==8)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines