LINUX.ORG.RU

Сочетание различных библиотек C++

 , ,


1

5

Здравствуйте, ЛОРчане.

Из того, с чем я работаю и учусь работать, в повседневной жизни я часто сталкиваюсь с 3 библиотеками : STL, Qt, Boost. Так получается, что функциональность у них в некоторых вопросах пересекается, взять хотя бы те же потоки(boost.pthread, std::thread, QThread).

Так вот, чему отдавать предпочтение? То есть допустим, что так получается, что в проекте нужно использовать эти 3 либы(пусть предположим, что от буста возьмём Graph, от культи интерфейсы как мимнимум, да и много чего там вкусного есть, ну от STL я так думаю можно тоже чего-нибудь взять).

В своём проекте я часто сталкиваюсь с ситуацией, что надо что-то выбирать из STL или из Qt : std::string vs QString, std::vector vs QVector. Но я не могу выработать правильную стратегию, когда и что стоит применять? Стоит ли, если используешь Qt, стараться по максимуму её юзать? Или стоит писать на смеси STL и Qt? Это касается естественно не только этих либ, но и других.

Как правильно поступают в таких ситуациях?

★★

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

Стоит ли если используешь Qt стараться по максимуму её юзать?

Да.

anonymous
()

Нативным С++ классам, конечно, до тех пор пока реализация функциональности не упрется в их ограничения (а там уж либо native_handle самому обрабатывать, либо брать из буста\кьюта).
Хотя, если пишешь qt-приложение, явно не стоит использовать буст или std, там где есть Qt аналоги.
Короче, стандартизация, удобочитаемость и переносимость — три приоритета, а там уж тебе решать на что делать бОльший упор.

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

просто мне кажется, что Qt это какой-то второй C++. Да, синтаксис тот же. Ну приправлено своим MOCom, но всё реализовано своё. И как-то посмотришь, сколько там вкусностей, и не хочется слазить на STL...

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

Qt это какой-то второй C++

Так и есть в принципе)

не хочется слазить на STL

Ну так не слазь, если пишешь графические Qt-приложения, пиши и не парься.
Консольные утилиты писать с Qt — изращение немножно, но никто не запретит.
Просто потом не удивляйся, если на ЛОРе в комментариях под твоим творением тебя обольют бассейном помоев х)

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

Да ладно, обольют все равно, на чем бы не написал.

ТС, пиши на Qt и не морочь голову всякими миксами.

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

культи
не тролль

Ok.

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

сейчас будет немного оффтопик, но всё же интересно : существует ли вероятность, что комитет по стандартизации расширит стандартные библиотеки C++ до уровня Qt?

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

std::string vs QString

std::string - это восьмибитная строка, в которой разумно хранить UTF8. QString - UTF16. На современной posix-системе все входные и выходные данные приложения используют кодировку UTF8, поэтому перекодирование вносит оверхед (который может быть очень нехилым если данных много). QString нужен только если ты собираешься передавать эту строку в кутишные API, например показывать эти строки в виджетах.

Однако есть кутишный QByteArray, который во многом приятнее std::string. Между ними имеет смысл выбирать исходя из того, нужен ли тебе CoW.

std::vector vs QVector

Если нужен CoW, бери QVector

Если ты пишешь библиотеку или каким-то другим образом твоими API пользуется много народу, то имеет смысл в публичных API ограничиться типами из Qt, для единообразия.

Еще такой момент: многие вещи в Qt за пределами осовной функциональности (QtCore и все виды GUI) реализованы хуже и/или менее гибко, чем в имеющихся сторонних библиотеках, реализующих аналогичную фунциональность. В частности, это относится к сетевому стэку, парсерам XML, QtSvg, QtTest, отчасти к контейнерам. Если какая-то функциональность является критической для твоего приложения, и реализация из Qt тебя чем-то не устраивает, то знай, что ты не один такой :)

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

Совсем до уровня Qt - нет, но некоторые возможности уже добавлены (например, потокии атомарные операции) или планируются (рефлексия).

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

про сравнения std::string vs QString я не имел в виду, что они одинаковы :) Ни в коем случае. Просто как сферический пример привёл:) Но во всём с Вами соглашусь.

Ну совсем это понятно. Всякие виджеты никто не потащит в плюсы, это точно. Но что насчёт работы с сетевым стеком? Удобные средства для тестирования? Парсеры? Это вполне можно было бы завезти. Слышал, что вроде как там ведутся работы по либе для работы с ФС. По идее введут с 17 стандартом или чуть позже (вроде как она не привязана к стандарту)

zamazan4ik ★★
() автор топика
Ответ на: комментарий от SysVinit-hater

какие есть ещё proposal, не подскажете? В плане расширения библиотеки

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

std::string vs QString

QString. Тут альтернатив просто нет.

Стоит ли если используешь Qt стараться по максимуму её юзать?

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

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

std::string - это восьмибитная строка, в которой разумно хранить UTF8

Если только хранить — то ещё может быть, но работать с юникодом оно не умеет:

xms@XMs-desktop ~/projects/tests/unicodestring $ cat main.cpp 
#include <iostream>
#include <string>
#include <cstdlib>

using namespace std;

int main()
  {
        string s("Тест");
        cout << s[0] << s[3] << endl; // expected: 'Т' and 'т'
        return EXIT_SUCCESS;
  }
xms@XMs-desktop ~/projects/tests/unicodestring $ g++ main.cpp 
xms@XMs-desktop ~/projects/tests/unicodestring $ ./a.out 
е
xms@XMs-desktop ~/projects/tests/unicodestring $ locale
LANG=ru_RU.utf8
LC_CTYPE="ru_RU.utf8"
LC_NUMERIC="ru_RU.utf8"
LC_TIME="ru_RU.utf8"
LC_COLLATE="ru_RU.utf8"
LC_MONETARY="ru_RU.utf8"
LC_MESSAGES="ru_RU.utf8"
LC_PAPER="ru_RU.utf8"
LC_NAME="ru_RU.utf8"
LC_ADDRESS="ru_RU.utf8"
LC_TELEPHONE="ru_RU.utf8"
LC_MEASUREMENT="ru_RU.utf8"
LC_IDENTIFICATION="ru_RU.utf8"
LC_ALL=
xms@XMs-desktop ~/projects/tests/unicodestring $

XMs ★★★★★
()

Qt — это и есть единственная причина писать на плюсах. Так что вот и ответ на твой вопрос.

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

существует ли вероятность, что комитет по стандартизации расширит стандартные библиотеки C++ до уровня Qt?

В C++17 планируется работа с ФС и сетью, да и интерфейсы контейнеров хотели унифицировать, так что в каком-то плане в этом направлении уже идут. Другой вопрос, насколько оно будет удобно для конечного разработчика — во многих аспектах Qt на порядок приятнее использовать, чем STL

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

Лень гуглить. Насколько эти работы с ФС и сетью будут обязательны? А то в C11 добавили threads.h, но, как я понял, оно опционально:

If the macro constant __STDC_NO_THREADS__ is defined by the compiler, the header <threads.h> and all of the names listed here are not provided.

SysVinit-hater
()
Ответ на: комментарий от zamazan4ik

С++17 многое обещает.
Не так широко, конечно, но все же там многое будет

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

для юникода вроде wstring

Размер wide char зависит от платформы, так что оно ещё хуже. В C++11 добавили u8"", u"" и U"", но оно, насколько я понял, в wide char перекодирует. В то время как QString берёт обычную строку безо всяких строковых литералов

XMs ★★★★★
()
Ответ на: комментарий от SysVinit-hater

Благодарю. Ещё бы имена классов более вменяемые были (что описывает класс ip::tcp? Нет, не протокол, а сокет, блджад! Почему нельзя было назвать его tcpsocket? То же самое к пространству имён ip, да и вообще ко многому, что есть в STL)

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

В то время как QString берёт обычную строку безо всяких строковых литералов

Ну, я бы так не сказал. Для QString есть QStringLiteral, через который строковые константы и лучше всего записывать (даром что сам кейворд громоздкий)

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

Прог которые используют Qt неявно тоже валом. К примеру doxygen. Он от Qt не зависит, но у него есть копии нужных ему Qt классов.

А все потому, что на stl писать мазохизм.

anonymous
()

Про MOC: он используется только есть в классе есть Q_OBJECT. При написании консольной утилиты/либы на QtCore без сигналов, он не нужен. Поэтому вполне реально писать сорцы так, что MOC не будет вызываться вообще.

Потоки в std и QtCore - это совсем разные вещи. std ничего не умеет.

std::vector и QVector различаются не только наличием CoW. У них разная реализация. QVector не кидает исключения и намного более приятный в работе. Иногда даже быстрее.

std::string vs QString

Ну тут и так все понятно. std::string для хранения или мазохистов. Использовать ее не для ASCII невозможно.

Вообще, если говорить об отдельных модулях, то у QtGui/QtWidgets вообще не альтернатив, QtCore >>>>> std, остальные модули в нагрузку, и их реально можно заметить более специализированными.

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

Для Юникода - ICU и другие библиотеки. wstring на онтопике не нужен, а на оффтопике его следует использовать только на границе с API.

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

wstring на онтопике не нужен

Сколько символов (а не байт) в юникодной строке? Как узнать? Как по ним проитерироваться?

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

Сколько символов (а не байт) в юникодной строке? Как узнать? Как по ним проитерироваться?

Как связан твой вопрос и wstring?

Freyr69 ★★★
()

Если с стл так всё грустно, то когда её вообще стоит использовать? То есть если я имею возможность притянуть кутю себе в проект, то её тянуть сразу стоит?

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

с stl все нормально. просто некоторые начали с Qt и получили синдром утенка. Qt5 внутри много stl юзает.

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

Всё зависит от задач. Если надо работать с текстом (не хранить, а именно работать — парсить, делить на подстроки, etc), то либо использовать QString, либо писать свой велосипед. Во втором случае, если сделаешь класс-обёртку над ICU, получится быстрее QString (поскольку, как уже писал annulen, текст чаще всего utf8, а QString хранит в utf16). Если строки просто хранятся и показываются пользователю — std::string с этой задачей справится без оверхеда.

Если ты пишешь сетевой сервер и ожидаемая нагрузка в районе 10 000 и меньше подключений единовременно, а времени у тебя мало либо хочется побыстрее расправиться с IO и сосредоточиться на обработчиках, то имеет смысл использовать QtNetwork. В противном случае тебе либо придётся извращаться (я, например, так и не понял, можно ли в сокет писать из одного потока, а читать из другого, по документации сокеты не потокобезопасны, хотя про сокеты в POSIX пишут иное), либо использовать более специализированные библиотеки, либо писать свои обёртки над сишными функциями. Хотя, если до этого дойдёт, то имеет смысл часть логики делать на чистых сях.

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

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

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

QStringLiteral

Почитаю, пока им пользоваться не приходилось. С другой стороны, у меня в строках кроме ASCII принципиально ничего нет (для локализации — QObject::tr())

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

Во втором случае, если сделаешь класс-обёртку над ICU, получится быстрее QString (поскольку, как уже писал annulen, текст чаще всего utf8, а QString хранит в utf16)

Внутреннее прдеставление в ICU тоже UTF16, хотя вроде есть примочки специально для UTF8. Другое дело, что ICU фичастее, но в Qt5 многое добавили.

Если ты пишешь сетевой сервер и ожидаемая нагрузка в районе 10 000 и меньше подключений единовременно, а времени у тебя мало либо хочется побыстрее расправиться с IO и сосредоточиться на обработчиках, то имеет смысл использовать QtNetwork

Я думаю для сервера лучше сразу брать подходящую серверную библиотеку, не дожидаясь пока понадобится обслужить больше клиентов, в QTcpServer нет никакой магии зато он использует тормозные QEventLoop и QIODevice. Речь конечно не идет о номинальном «сервере», встроенном в клиентское приложение со штатной нагрузкой не более 1 клиента :)

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

но в Qt5 многое добавили

А что там добавили касательно QString и юникода?


в QTcpServer нет никакой магии зато он использует тормозные QEventLoop

Его можно использовать без eventloop-а

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

QVector не кидает исключения

А std::vector когда их кидает? Ну кроме метода at.

и намного более приятный в работе

Чем?

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

У меня в проекте как раз работать приходится со строками, написал свои велосипеды для работы с UTF8 наподобие такого:

inline std::string encodeUTF8 (wchar_t uc) {

	std::string ret;
	unsigned char b1, b2, b3, b4;//, b5, b6;

	if (uc == 0x0040) return "";
	if ((uc >= 0xD800 & uc <= 0xDFFF) == 1) return "";

	if ((uc > 0x1 & uc <= 0x007F) == 1) {

		ret += uc;

	} else if ((uc > 0x007F & uc <= 0x07FF) == 1) {

		b1 = 0xC0 | (uc & 0x7C0) >> 6;
		b2 = 0x80 | (uc & 0x3F);

		ret  = b1; ret += b2;

	} else if ((uc > 0x07FF & uc <= 0xFFFF) == 1) {

		b1 = 0xE0 | (uc & 0xF000) >> 12;
		b2 = 0x80 | (uc & 0xFC0) >> 6;
		b3 = 0x80 | (uc & 0x3F);

		ret  = b1; ret += b2; ret += b3;

	} else if ((uc > 0xFFFF & uc <= 0x10FFFF) == 1) {

		b1 = 0xF0 | (uc & 0x1C00000) >> 18;
		b2 = 0x80 | (uc & 0x3F000) >> 12;
		b3 = 0x80 | (uc & 0xFC0) >> 6;
		b4 = 0x80 | (uc & 0x3F);

		ret  = b1; ret += b2; ret += b3;
		ret += b4;
	}

	return ret;
}

Но когда встала необходимость преобразовать std::string в std::wstring у меня начались проблемы, на онтопике все работает, а на оффтопике все падает, с файла хочу читать уникодные символы и записывать в std::wstring, сделал как-то так:

inline std::wstring str2wstr (const std::string &s) {

	std::wstring ws (s.size(), L' ');
	ws.resize (mbstowcs (&ws[0], s.c_str(), s.size()));

	return ws;
}

Тянуть ради строк QT не хочется. Как лучше поступить в данной ситуации, переходить на ICU? Или может уже допилить велосипед )

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

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

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

а на оффтопике все падает

потому что там wchar_t это 2 байта? std::u32string тебе в руки. или тупо std::basic_string<std::uint32_t>

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

Суть в том, что QVector можно спокойно использовать, зная что никаких исключений не будет.

Чем?

Как минимум тем, что у него методов раза в два больше. Есть удобные: <<, indexOf(), contains(), prepend(). Можно добавить вектор к вектору.

PS: exceptions hater, по этому этот пункт можно даже не обсуждать.

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

Есть удобные: <<, indexOf(), contains(), prepend(). Можно добавить вектор к вектору.

омг! А я всегда говорил, что Qt калечит моск.

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

Суть в том, что QVector можно спокойно использовать, зная что никаких исключений не будет.

Дык, как раз интересно откуда исключения возьмутся в std::vector, а то я его всё время тоже «спокойно использовал».

Есть удобные: <<, indexOf(), contains(), prepend(). Можно добавить вектор к вектору.

Всё это есть и в stl, пусть и в виде внешних алгоритмов. Чуть более громоздко из-за итераторов, но и более гибко. Принципиальной разницы нет.

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

Но когда встала необходимость преобразовать std::string в std::wstring у меня начались проблемы, на онтопике все работает, а на оффтопике все падает

Размер wchar зависит от платформы, вангую, что проблема в этом.


Как лучше поступить в данной ситуации, переходить на ICU?

Лично я чаще всего использую QString, но у меня в проектах Qt довольно широко используется, так что это не аргумент. К плюсам перехода на ICU можно отнести то, что оно уже готово, под пермиссивной лицензией (если проект рабочий, это может быть важно) и обновляется штатными средствами. К минусам — дополнительная зависимость. Вообще, прежде чем определяться с таким решением, стоит решить, а нужно ли реально работать с не-ASCII символами. Если да — переходи, если дополнительная зависимость погоды не сделает, если нет (например, ты пишешь парсер текстового протокола) — то лучше вообще отказаться от обработки нелатинских символов

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

Есть удобные: <<, indexOf(), contains(), prepend(). Можно добавить вектор к вектору.

А также есть неспособность QVector хранить значения типов без конструктора по-умолчанию, неспособность инициализировать вектор парой итераторов.

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

Ну у меня парсер ML языка, там он простенький, но все же из переменных требуется выдерать надписи с русскими или китайскими символами, только в этом проблема. Да скорее всего из-за wchar, переделаю на std::u32string

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

Дык, как раз интересно откуда исключения возьмутся в std::vector

out-of-range, bad_alloc, ещё какие-то были. Это те, что могу вспомнить сходу

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

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

Тогда можно просто брать позицию первого не-ASCII символа как начало, первый ASCII-символ не-пробел как конец, и вот тебе, считай, выдранная надпись

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

out-of-range

Только если используешь «at» вместо «[]». То есть, если сам попросишь использовать исключения.

bad_alloc

Most desktop operating systems overcommit memory. This means that malloc() or operator new return a valid pointer, even though there is not enough memory available at allocation time. On such systems, no exception of type std::bad_alloc is thrown.

On all other operating systems, Qt will throw an exception of type std::bad_alloc if any allocation fails.

То есть поведение Qt и stl в этом вопросе никак не отличается.

ещё какие-то были

Ещё length_error в reserve (довольно экзотический случай) и всё.

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

Вкусовщина конечно, но:

vector<int>::iterator idx = lower_bound(v.begin(),v.end(), num);
out << idx - v.begin() << endl;
никак не лучше:
qDebug() << v.indexOf(num);

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

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