LINUX.ORG.RU

Как убрать прямое обращение к переменной в шаблоном классе.

 


0

1

Есть в библиотеке такой класс, TAutoClose, освобождающий ресурсы своего члена класса, вызывая его метод Close(), при выходе из области видимости. При этом глаза мозолит использование iObj:

TAutoClose<RApaLsSession> cmd;
cmd.iObj.Connect();
cmd.iObj.Send();

Хочу так:

cmd.Connect();
cmd.Send();

Добавил реализацию оператора &(видел подобный фокус с оператором '*' для умных указателей), всё равно компилятор говорит, что не видит функции:

T& operator&() {
return iObj;}

Вот общий вид этой группы классов: TAutoClose освобождает ресурсы группы классов вида:

class RExample:
{
   int handle;
public:
   void Close() {}
}

И сам класс:

template <class T>
class TAutoClose
/**
@publishedAll

Automatically calls Close() on an object when that object goes out of scope.
The behaviour takes advantage of the fact that the compiler automatically
destroys objects that go out of scope.
*/
    {
public:
    inline ~TAutoClose();
private:
    static void Close(TAny *aObj);
public:
    /**
    An instance of the template class.
    */
    T iObj;
    };

// Class TAutoClose
template <class T>
inline TAutoClose<T>::~TAutoClose()
/**
Destructor.
The implementation calls Close() on iObj, the instance of the template class.
*/
    {iObj.Close();}
 
template <class T>
void TAutoClose<T>::Close(TAny *aObj)
    {((T *)aObj)->Close();}


Точка не перегружается. Можно перегрузить -> и юзать как cmd->Connect();

Ну или добавить обертки для всех методов какие хотите скрывающих iObj, но это будет много букв.

AntonI ★★★★
()
Последнее исправление: AntonI (всего исправлений: 2)

Осталось понять зачем нужен этот велосипед вместо стандартных unique_ptr и shared_ptr, у них есть deleter-ы.

Begemoth ★★★★★
()
Последнее исправление: Begemoth (всего исправлений: 1)

Забей на это, серьёзно. Потому как глаза здесь мозолит абсолютно всё, начиная с TTypeName и заканчивая нечитаемым форматированием с полностью бесполезными комментариями.

anonymous
()
Ответ на: комментарий от Begemoth

Осталось понять, куда ты будешь пихать объект в unique_ptr(в делетер) и как будешь выкидывать оттуда ненужный указатель(никак). Данный велосипед примерно такого же как ты уровня люди и написали.

anonymous
()
Ответ на: комментарий от anonymous
#include <cstddef>
#include <memory>

template <typename T, T NullValue>
struct handle_as_ptr {
    handle_as_ptr(T handle = NullValue) : value_(handle) {}
    handle_as_ptr(std::nullptr_t) : value_(NullValue) {}
    explicit operator bool() const { return value_ != NullValue; }
    operator T() { return value_; }
    bool operator==(const handle_as_ptr& rhs) const {
        return value_ == rhs.value_;
    }
    bool operator!=(const handle_as_ptr& rhs) const { return !(*this == rhs); }

  private:
    T value_;
};

template <typename Pointer, auto DeleteFunc>
struct generic_deleter {
    using pointer = Pointer;
    void operator()(pointer ptr) { DeleteFunc(ptr); }
};

template <typename T, T NullValue, auto DeleteFunc>
using unique_handle = std::unique_ptr<
    void, generic_deleter<handle_as_ptr<T, NullValue>, DeleteFunc>>;

Использую примерно так

// POSIX file descriptor
using file_descriptor = unique_handle<int, -1, ::close>;
anonymous
()
Ответ на: комментарий от anonymous

Во первых ты написал кода больше чем в ОП - сделать такое же форматирование и накидать «комментариев» - будет простыня на два экрана. Во вторых у тебя там void*, который никак не используется и ненужен в данном случае, но убрать ты его не сможешь.

Даже код ТС’а чуть ли не эталон по сравнению с этим. Ну и конечно же, разлогин, куда без этого.

anonymous
()
Ответ на: комментарий от anonymous

Во вторых у тебя там void*

static_assert(sizeof(unique_handle<short, -1, ::close>) == sizeof(short));

На остальной бред отвечать не буду.

anonymous
()

Не могу понять задумку авторов этого кода. Обертка TAutoClose имела бы смысл, если бы часть хранимых объектов T должна была вызывать Close() перед вызовом деструктора, а другая часть нет. Но я не могу представить себе ситуацию, когда некая сессия не должна закрываться, когда отвечающий за нее объект уничтожается. Складывается впечатление, что это написал некий дельфист, недавно открывший для себя удивительный мир С++ и его шаблонов. Проще надо быть.

annulen ★★★★★
()
Ответ на: комментарий от annulen

Хе, принцип работы такой:

  1. Создаём на стеке переменную внутри нашей обертки
  2. Пользуем
  3. При выходе из функции вызывается деструктор и закрывает клиентскую сессию
  4. Профит!
zanac1
() автор топика
Ответ на: комментарий от zanac1

Но гораздо проще и логичнее это сделать в деструкторе самого класса, а если таких классов много и они не в одной иерархии, то сделать им общий базовый класс. И все, никаких перегрузок операторов и псевдоумных псевдоуказателей

annulen ★★★★★
()
Ответ на: комментарий от zanac1

Желательно как внешний оператор, не меняя TAutoClose.

Мне страшно за твоих коллег

annulen ★★★★★
()
Ответ на: комментарий от zanac1

TAutoClose - вот эта штука любому знающему человеку напоминает умный указатель вроде unique_ptr (особенно если добавить перегрузку ->), но на деле им не является

annulen ★★★★★
()
Последнее исправление: annulen (всего исправлений: 1)
Ответ на: комментарий от zanac1

Получилось такое: T* operator->() {return &iObj;}.

Даже собралось и работает в маленьком примерчике...

zanac1
() автор топика

Код уебков.

anonymous
()
Ответ на: удаленный комментарий

Да не гони, всё верно первый анонимус делает.

handle_as_ptr с его конструктором нужен, чтобы тип был NullablePointer, это требование unique_ptr.

А static_assert проходит, потому что unique_ptr<T,Deleter> хранит не T*, а Deleter::pointer.

Как по мне, так первый анонимус знает толк в извращениях, но мне было б лениво постоянно писать file_descriptor.get().

P.S. Первому анонимусу спасибо, фишку с Deleter::pointer я не знал.

JaM
()
Последнее исправление: JaM (всего исправлений: 2)
Ответ на: комментарий от JaM

handle_as_ptr с его конструктором нужен, чтобы тип был NullablePointer

Да, понял я уже. Вам (тебе и тому агрессивному анониму) не нравится имя класса handle_as_ptr. Мне тоже. Ну поменяйте на свою любимое имя, например, nullable_pointer. Но…

Работает, же ж!

Deleter::pointer я не знал.

Ты бы знал сколько я копал исходники stdlib ради этой заветной строчки…

template <typename Pointer> struct generic_deleter { using pointer = Pointer; }

Я, кстати, не уверен, что это соответствует стандарту с++

anonymous
()

Хм, каждое следующее поколение плюсистов все меньше знает и понимает плюсцы. Иронично!

anonymous
()
Ответ на: комментарий от anonymous

Хм, каждое следующее поколение критиков все меньше знает и понимает, чем критикует. Иронично!

anonymous
()
Ответ на: комментарий от anonymous

Ты бы знал сколько я копал исходники stdlib ради этой заветной строчки…

Когда ты это делал?

anonymous
()
Ответ на: комментарий от anonymous

Не сегодня и не для тебя.

А может и вообще не копался, т.к. как совать хэндлы в unique_ptr на SO описано почти 10 лет назад.

Сливайся уже, проверяльщик static_assert’ов.

Мимо

anonymous
()
Ответ на: комментарий от anonymous

как совать хэндлы в unique_ptr на SO описано почти 10 лет назад.

Ссылку. Чтобы именно через подмену pointer. Это тут эксперты не могут избавиться от указателя.

И да, чтобы было 10 лет назад.

anonymous
()
Ответ на: комментарий от anonymous

Конкретные решения с подменой pointer даны в 2018

Замена поинтера есть уже в вопросе. И конкретное решение дано в отмеченном ответе от 2013-го года.

anonymous
()
Ответ на: комментарий от anonymous

И конкретное решение дано в отмеченном ответе от 2013-го года.

А ты посмотри историю изменений этого «ответа». Рабочим он стал только в 2018.

Это как здесь на лоре: застолбили пустое сообщение, и редактируют вечность - карму зарабатывают.

anonymous
()
Ответ на: комментарий от anonymous

А ты посмотри историю изменений этого «ответа».

Там мелкие фиксы вроде замены «нулевого» дескриптора с 0 на -1.

В общем, ладно. Держи свой патент на использование unique_ptr для управления файловыми дескрипторами.

anonymous
()
Ответ на: комментарий от anonymous

А тут надо указывать лицензию на написанные сообщения? Если да, то хочу чтобы, никто кроме меня, то есть нас, анонимов, не мог использовать этот код. :)

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.