LINUX.ORG.RU

Как обратиться к std::shared_ptr<void> ???

 


0

2

Подскажите как правильно тип привести, чтобы подсчет ссылок не поломался?

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

std::shared_ptr<linphone::Core> core >>> std::shared_ptr<void> core

проинициализировалось

auto factory = linphone::Factory::get();
core = factory->createCoreWithConfig(config, nullptr);

Как теперь здесь обратиться корректно???

...core...->addListener(std::make_shared<ClientCoreListener>())
★★★

Ответ на: комментарий от ox55ff

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

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

разница в том, что инклуд этой декларации происходит в других местах

Какая возникает проблема от этого? У тебя компиляция ошибкой заканчивается? Нет никаких проблем.

Твой подход с void абсолютно не годится, потому что становится непонятно какой там должен быть тип. А что если ты ошибёшься и засунешь туда не тот тип. При вызове у тебя программа завалится, а ты будешь очень долго и нудно отлаживать. Не надо так писать. Это write-only код, в котором потом невозможно будет разобраться. Цпп - язык со статической типизацией. Не нравится типизация накати питончик и суй любые типы куда захочешь, превращая код в лапшу.

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

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

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

тип спрятан, а пространство имен в класс не прячется

остановлюсь на этом совете Как обратиться к std::shared_ptr<void> ??? (комментарий)

в заголовке
std::shared_ptr<void> core;

в реализации
(reinterpret_cast<linphone::Core*>(core.get()))->addListener(std::make_shared<ClientCoreListener>())

спасибо за помощь, особенно @Ivan_qrt

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

Как-то все переусложнено имхо.

Как вариант могу предложить следующее извращение, в заголовке сделать шаблон с core, а в реализации специализировать исключительно для linphone::Core. Так типизация будет работать и магия указателей не нарушит токи энергий: дорога в наш мир для сил хаоса будет закрыта … :)

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

т.е. шаблон + класс или как то можно один шаблон сделать?

да все просто на самом деле… единственно непонятно

(reinterpret_cast<linphone::Core*>(core.get()))

удерживает ли счетчик ссылок или указатель вдруг внутри может освободиться

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

Счётчик ссылок при этом вообще не трогается.

Сперва выполняется core.get(), возвращающий сырой указатель (не трогая счётчик ссылок). Все остальные операции проводятся уже над ним, без обращений к shared_ptr. При этом сам reinterpret_cast вообще ничего в бинарнике не делает и инструкций не содержит. Это всего-лишь указание для компилятора сменить тип.

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

т.е. шаблон + класс или как то можно один шаблон сделать?

да сделать CSIP шаблонным классом к примеру:

template<typename SomeCore>
class CSIP
{
private:
    std::shared_ptr<SomeCore> core;
...

// специализация класса
template<>
class CSIP
{
private:
    std::shared_ptr<linphone::Core> core;
...

Остальные варианты инстанцирования шаблонов другими типами можно запретить при желании.

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

Да не, там Type Erasure. Всё можно привести к void *, и там конструирование от конкретного класса, соответственно и делитер формируется, а когда сохраняется в ptr, то передаётся и делитер для конкретного класса, соответственно - он и вызовется и всё, что нужно подчистить, уже зная, для какого класса он создан. Type Erasure паттерн. Ну и сохранение семантики: всё можно в void *.

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

Не в этом несколько вопрос, про макрос я прочитал после вашего примера, речь о том что может ли шаред птр освободить указатель, пока он где то используется он напрямую

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

Если используется полученный по .get() сырой указатель, то конечно может, поэтому сохранять на долгое время указатель из reinterpret_cast’а нельзя. Но покуда у тебя жив твой shared_ptr, указатель тоже будет жив. Учитывая, что он у тебя уничтожается только в деструкторе, то во всех методах CSIP ты можешь спокойно рассчитывать на то, что указатель жив.

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

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

Ещё раз премного благодарен за ликбез.

wolverin ★★★
() автор топика

Так делать нельзя, потому что shared_ptr должен знать как удалять твой объект. А удалить он его может при каждом выходе указателя из области видимости, а том числе в пользовательском коде.

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

А что поменяется!? Я буду глобальную переменную присваивать локальной и весь метод с ней работать без приведения типов даже макросом.

Сейчас в инициализации сделал наоборот и выглядит по красоте.

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

наверняка работает с unique_ptr

Компилируется ещё не значит работает. Оно вызовет деструктор для void, который ничего не делает. Если у linphone::Core нетривиальный деструктор, у тебя случится UB от утечки памяти (если деструктор что-то освобождал) до висящего указателя (если деструктор убирает ссылки на удаляемый объект из других мест). Не надо делать UB, лучше сделать инклюд.

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

Сходи к психологу и проработай травмирующие ситуации из прошлого, чтобы справится со страхом инклюдов.

Скорее всего проект был на plain C, где нету неймспейсов и библиотеки действительно иногда конфликтуют. Шанс того что кто-то левый объявит неймспейс linphone стремится к нулю.

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

на всякий случай счётчик в начале и в конце увеличивается и уменьшается принудительно

Это вообще абзац. Ты не понимаешь что происходит у тебя в коде. Наворотил столько костылей вместо использования стандартного подхода с forward declaration.

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

)) мне эти два языка ещё со школы нравятся лишь потому, что можно делать хоть как, ничего не ограничивает, единственно заметил что от версии gcc зависит что некоторые конструкции перестают работать в следующих версиях ))))

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

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

Отсюда и все твои сложности в написании и понимании кода. И в том, что твой код ломается при смене версии компилятора. (справедливости ради, такое почти у всех случается. На плюсах писать так, чтобы совершенно точно совсем без ub было крайне сложно, если вообще возможно. Но ломаться код от смены компилятора в норме должен крайне редко.)

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

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

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

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

Бред.

Да, копирование shared_ptr дороже копирования простого указателя.

Нет, это не «очень медленная процедура» – это один доступ к памяти и один relaxed инкремент.

Ты не заметишь никакой разницы, потому что запись на флешку одного кадра займет в десятки, если не сотни тысяч раз больше времени. Еще больше ты сэкономишь, если прекратишь страдать «полезным делом», почитаешь-таки советы, которых тебе написали множество в твоих топиках, и переделаешь архитектуру своих поделок.

Да даже не говоря об этом – ты «экономишь» на копировании shared_ptr, но в прошлом топике переаллоцировал std::string на каждый чих. Это несоразмерно дорого.

Ты читаешь какой-то бред в интернете, и применяешь к себе, не понимая ни того, что читаешь, ни того, что делаешь. Вместо воинствующего невежества, которым ты тут занимаешься уже год (?) на деньги работодателя, изучи лучше C и C++ на должном уровне.

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

переалокация стринга там происходит от действий юзера при нажатии на клавиатуру на устройстве и это никак не может быть быстрее 50мс при чтении с уарта

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

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

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

))) и да - конкретно сейчас это и есть переделка архитектуры предыдущего разработчика, который вместо «нормально делай - нормально будет» написал говно, которое каждые 5 дней ребутится, чтобы с утечками в коде не бороться (цитата не дословная), а советовали мне здесь вместо сделать все с нуля выкинув лишнее - заниматься анализом ранее написанного говна.

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

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

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

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