Russian Qt Forum
Ноябрь 23, 2024, 11:26 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало Форум WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  
  Просмотр сообщений
Страниц: [1] 2 3 ... 6
1  Qt / Общие вопросы / Re: Опредение того, является ли каталог подкаталогом другого : Ноябрь 18, 2021, 07:02
Да! Я бегло смотрел на QUrl (поскольку знал, что в .NET-овской Url есть такой функционал) ... и просмотрел! Возможно, это хорошее решение. Но как она с симлинками (нужно резолвить)?
2  Qt / Общие вопросы / Re: Опредение того, является ли каталог подкаталогом другого : Ноябрь 17, 2021, 21:05
Да, при условии что оба каталога существуют. Только использовать canonicalPath(), т.к. она резолвит симлинки.

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

Эти QDir, QQFileInfo и т.п. "относительно ленивы". В том смысле, что если директория/файл не существует, то ф-ии типа absolutePath() не будут работать (возвращают пустые строки).

Собственно, ядро проблемы - для произвольного пути (возможно, пока несуществующего) получить canonicalPath(). А дальше так, как вы указали. Поэтому, если есть каталог "/a/b/c//d/..///./e", то нужно самому сделать то, что делает canonicalPath(). Только это будет чисто строковая обработка. Альтернативно (много проще), временно создать этот каталог и заюзать QFileInfo::canonicalPath, но это как-то топорно. Как-то так мыслю.
3  Qt / Общие вопросы / Опредение того, является ли каталог подкаталогом другого : Ноябрь 17, 2021, 06:47
Друзья, заданы два каталога. Это могут быть абсолютные пути, относительные, с симлинками, .. что угодно. Пути локальные. Нужно установить, не является ли один подкаталогом другого (любого уровня).

Qt 5.15. Собственно, в QDir, QQFileInfo я не вижу нужной функции. Неужели мне cdUp()-ить от одного и сравнивать со вторым и наоборот (ну, или там в canonicalPath() подстроки искать)? std::file_system - как там?

Спасибо.
4  Компиляторы и платформы / Mac OS X / Запрет автогенерации LaunchScreen.storyboard (Qt 5.15/iOS) : Сентябрь 02, 2021, 06:06
Мне не нужен генерируемый qmake'ом по дефолту LaunchScreen.storyboard, ибо используется свой. Потроха этого процесса находятся в mkspecs/features/uikit/default_post.prf. Сходу не разобрался как отключить (не правя сорцы).

Вообще, мне нужна локализованная версия дефолтного LaunchScreen.storyboard (там только имя приложения на белом фоне).
5  Qt / Установка, сборка, отладка, тестирование / Qt 5.15.2 for Android: build.gradle: неверное указание buildToolsVersion : Июль 23, 2021, 09:44
В файле ~/Qt/5.15.2/android/src/android/templates/build.gradle имеем следующее:
Код:
buildToolsVersion '28.0.3'
С какого здесь хардкорная версия? Напомню, это исходный шаблон, и он копируется при сборке Qt-Android приложения.
Должно же быть
Код:
buildToolsVersion androidBuildToolsVersion
где androidBuildToolsVersion уже изменяются через локальный gradle.properties проекта.

Если нет некоего тонкого момента, которого я сходу не улавливаю, возможно, связанного с совместиностью версий, то это просто небрежный баг, свидетельствующий о снижении качества разработки Qt/
6  Qt / Qt Quick / Получить applicationDirPath из QML-файла : Июнь 18, 2021, 19:19
Акромя установки контекстного свойства из C++
Код:
engine.rootContext()->setContextProperty("applicationDirPath", QGuiApplication::applicationDirPath());
это как-то возможно? Вот вижу, что Qt.application обделен этим.

P.S. Нужно сохранять размер/позицию и т.п. QML окна с помощью Settings в ini-файл, лежащий рядом с экзешником.
7  Qt / Общие вопросы / Re: QCoreApplication::exec(): определение нахождения вне этой функции : Май 02, 2021, 12:29
QThread::currentThread()->loopLevel(); - похоже, оно! Since Qt 5.5.
8  Qt / Общие вопросы / QCoreApplication::exec(): определение нахождения вне этой функции : Май 02, 2021, 08:44
Как внутри foo() мы можем определить, что foo() вызвана не из QCoreApplication::exec(), а из точек 1 или 2?
Код:
static void foo()
{
...
}

int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
foo();  // 1
const int result = QCoreApplication::exec();
foo();  // 2
return result;

}

Вообще есть QEventLoop::isRunning(). Альтернативно - как добраться до экземпляра QEventLoop главного потока? Сходу из документации не могу выудить.

Есть еще QCoreApplication::eventDispatcher(), но он создается вне QCoreApplication::exec().
 
9  Программирование / С/C++ / Re: Итераторы : Апрель 25, 2021, 09:59
Да, любовь - странная штука:
Код:
#include <QSet>
#include <iostream>

using namespace std;

typedef int CData;
using CDataRef = reference_wrapper<CData>;

QSet<CData*>* mSelection = new QSet<CData*>;

QSet<CDataRef>*& SelectionAsRefs( void )
{
static_assert(sizeof(CData*) == sizeof(CDataRef));
return *(QSet<CDataRef> **) &mSelection;
}

static QSet<CData*>* makeUB(QSet<CData*>** src, QSet<CDataRef>** alias)
{
static QSet<CData*> data = { new CData };  // set with one element

*src = &data;
*alias = nullptr;

return *src;  // what will be there: &data or nullptr?
}

int main(int, char *[])
{
mSelection = makeUB(&mSelection, &SelectionAsRefs());
std::cout << (!mSelection ? "OK" : "UB") << std::endl;
}
Этот код дает UB при -O2. Я вынужден был перейти от QSet<CData*> к QSet<CData*>*. Непосредственно тип QSet<CData*> UB не дает. Полагаю, что давал бы, если бы в нем был "простой" конструктор.
10  Программирование / С/C++ / Re: Итераторы : Апрель 24, 2021, 21:57
Те же яйца, только в профиль:
Код:
int i;
void* p;  // declaration
p = &i;  // p begins its lifetime with dynamic type int*

memcpy: Notes

std::memcpy may be used to **implicitly create** objects in the destination buffer.
...
Where strict aliasing prohibits examining the same memory as values of two different types, std::memcpy may be used to convert the values.

И далее почитать по ссылке https://en.cppreference.com/w/cpp/language/object#Object_creation что такое объекты и как они создаются.
11  Программирование / С/C++ / Re: чтение и запись битовых структур данных : Апрель 24, 2021, 15:58
В плане использования на уровне бизнес-логики - просто наложить placement new:
Код:
// Packed data
struct A {
  int a; // 2 bits
  int b; // 15
};

// State less business-logic class
class UnpackedA
{
public:
int a() const { return *reinterpret_cast<const int*>(buf()) & 0x3; }
int b() const { return *reinterpret_cast<const int*>(buf() + sizeof(int)) & 0x7FFF; }

private:
// Returns buffer of packed data
const char* buf() const { return reinterpret_cast<const char*>(this); }
};

int foo() {
A a;  // e.g. got from network
auto ua = new (&a) UnpackedA;
}

Это я привел вариант для чтения (распаковки) данных. Для записи (упаковки) - абсолютно тоже самое, только в другую сторону.

Да, и здесь класс бизнес логики предполагает время жизни буфера большим своего. Короче, этот класс - интерпретатор, создаваемый по месту. Ну как бы не совсем бизнес-логика, а скорее хелпер.
12  Программирование / С/C++ / Re: Итераторы : Апрель 24, 2021, 15:46
Цитировать
"стартует как"
Код:
void* p;          // declaration
p = new int(5);   // p begins its lifetime with dynamic type int*

Вот здесь по сути вопроса изложено четко и с примером: https://en.cppreference.com/w/cpp/string/byte/memcpy
13  Программирование / С/C++ / Re: Итераторы : Апрель 24, 2021, 14:28
Да, и в С++20 это делается уже так (std::bit_cast):
Код:
QSet<std::reference_wrapper<CData>>& mSelectionAsRefs() 
{
static_assert(sizeof(CData*) == sizeof(std::reference_wrapper<CData>));
return std::bit_cast<QSet<std::reference_wrapper<CData>>&>(mSelection);
}
Т.е. дали заднюю со своим strict type aliasing.

Еще вариант (ИМХО, в общем случае малоприемлемый) - выключить strict type aliasing опцией компилятора. Ядро Линукса, например, компилится с -fno-strict-aliasing, а там, как можно догадаться, еще те любители реинтерпретации.
14  Программирование / С/C++ / Re: Итераторы : Апрель 24, 2021, 12:02
С вашего позволения вернусь к обозначенной проблеме UB reinterpret_cast'a. Изначальный вариант:
Код:
QSet<std::reference_wrapper<CData>>& mSelectionAsRefs() 
{
static_assert(sizeof(CData*) == sizeof(std::reference_wrapper<CData>));
return reinterpret_cast<QSet<std::reference_wrapper<CData>>&>(mSelection);
}
полагаю, можно сделать полностью безопасным вот так:
Код:
QSet<std::reference_wrapper<CData>>& mSelectionAsRefs()
{
static_assert(sizeof(CData*) == sizeof(std::reference_wrapper<CData>));

QSet<CData*>* src = &mSelection;
QSet<std::reference_wrapper<CData>>* alias;

std::memcpy(&alias, &src, sizeof(alias));  // starts lifetime of alias as QSet<CData*>*
return *alias;
}
Фишка этого приема в том, что memcpy() дает понять компилятору, что alias стартует как тип src, т.е. QSet<CData*>*.

Или эквивалент (м.б. более понятный):
Код:
QSet<std::reference_wrapper<CData>>& mSelectionAsRefs()
{
static_assert(sizeof(CData*) == sizeof(std::reference_wrapper<CData>));

QSet<CData*>* src = &mSelection;
void* alias;

std::memcpy(&alias, &src, sizeof(alias));  // starts lifetime of alias as QSet<CData*>*
return *static_cast<QSet<std::reference_wrapper<CData>>*>(alias);
}
Здесь alias прямо декларируется как void* - тип, полностью совместимый с любым указателем (альтернативно, можно char* alias[sizeof(src)]), и далее используется static_cast.

Естественно, после оптимизации новый вариант относительно старого не должен иметь никаких дополнителных расходов.

Остается только одна потенциальная проблема - возможная специализация контейнера для указателей. В принципе, ее легко решить, если сделать свою специализацию контейнера для std::reference_wrapper<CData>, которая будет иметь битовую идентичность с контейнером CData*. Но это лениво (много букв).
15  Программирование / С/C++ / Re: Итераторы : Апрель 23, 2021, 11:26
Цитировать
Рекомендация выше юзать ссылку (вместо указателя). Обычно я охотно это делаю, но в данном случае это "создает впечатление владения", а selection ну вот никак не владеет. Некоторый минус - QSet жрет многовато памяти при обильном selection.
В этом правда есть.

Изложу лишь следущее: если бы selection был владеющий отдельной копией объекта, т.е. QSet<CData> (не CData*) - это как-то принципиально сломало бы ваш код? Предположу, что нет. Указатель вы используете для уменьшения потребления памяти, ну и бонусом хэш-функция уже есть. Т.е. использование в selection указателей или самих данных определяется их размером, что, согласитесь, семантически ничтожный аргумент. Поэтому ссылка в данном случае - это эффективное владение.

Я допускаю, что выбор указателя может быть как-то связан с хэшированием, например CData неуникальны. Или для них нетривиально придумать хорушую хэш функцию. 

Ваш код был бы проще, если бы было единообразие, которое позволило бы единую обработку шаблонной функцией без is_pointer:
Код:
struct CBigClass {
...
 QList<CData*> mData;
 QSet<CData *> mSelection;
...
}

или

struct CBigClass {
...
 QList<CData> mData;
 QSet<reference_wrapper<CData>> mSelection;
...
};

Порядок таков, что если CData - это класс-сущность (identity class), то используются указатели, если класс данных - то сами классы.

Цитировать
Не думаю здесь есть какие-то "варианты зависящие от задачи"
От специфики задачи зависит, порой, все  Улыбающийся Если у вас часто случаются пулеметные вставки, может рассмотреть вариант сперва сформировать вставку в виде вектора, а потом вставить ее в контейнер как единое целой, т.е. никаких multiply вставок?

Цитировать
Или популярная байка "std::vector лучше"  (чем QList).
Ну как байка? Например, в QList не засунешь std::unique_ptr, а std::unique_ptr в контейнере - это сплошь и рядом. Да, вы можете засунуть std::shared_ptr/QSharedPointer - но это другая (более широкая) семантика, да и код будет менее эффективным.

Например, QList нет еmplace, а еmplace, в свою очередь, может оказаться решающим доводом в пользу типа данных контейнера, соот-но QList дает меньшую свободу.
Страниц: [1] 2 3 ... 6

Страница сгенерирована за 0.053 секунд. Запросов: 23.