Об том и речь. А по поводу «ожидаемой области применения»… У меня сложилось впечатление, что автор статьи сам слабо себе представляет цену тех советов, которые даёт. Такое впечатление сложилось вот почему. В первой части (про pragma pack) резюме такое: «Если вам мешает паддинг, выкиньте его с помощью прагмы!». И ни слова о том, зачем паддинг нужен, и почему от него надо избавляться только в самом крайнем случае. Из содержимого третьей части можно сделать вывод, что автор предлагает читать заголовок TCP/IP-пакета сразу в предложенную структуру. При этом нет ни слова о том, что, вообще говоря, структура эта не является POD-типом (потому что в ней присутствуют не-POD типы — те самые u16be), и такие манипуляции с ней не рекомендуются. Таким образом, в случае компиляции всего этого дела одним конкретным компилятором (Visual C++) может работать, а другом — нет.
А если не раскидает? Да и вообще, с какой стати компилятор должен раскидывать доступ к таким данным? Нет, может быть за последние 6 лет что-то и изменилось, но в середине 2000-ых сановские компиляторы таким точно не страдали.
Протокол обмена — это, обычно, хорошо стандартизированная и описанная штука. И данные, которые ходят по этому протоколу, совсем не обязательно должны «ложиться» на их бинарное представление в памяти. Более того, то, что они в данном конкретном случае ложатся — это большое везение. :) По этому при получении данных их таки лучше разобрать «ручками», и разложить по полям структуры, чем играть в рулетку и надеяться на то, что авось повезёт, и данные в память лягут так, как надо.
Это всё, конечно, хорошо. Но, как уже правильно отметили в комментариях, непереносимо, а на некоторых платформах и попросту небезопасно. Из лично известных мне — SPARC весьма щепетильно относится к выравниванию данных, и генерит исключение SIGBUS в случае доступа к неправильно выравненным данным.
Спасаться от лишнего паддинга можно и без pragma pack. Рецепт прост — поля в структуре «сортируются» по размеру. В начале помещаются самые большие (uint64, uint32), в конце — самые маленькие — (uint8). Все вопросы с порядком байт должны (на мой взгляд) решаться в точке сериализации и десериализации данных (ну, например, при отправке в сеть и получения из сети), а сам этот процесс, по хорошему, должен производиться не сразу в структуру, а путём последовательного чтения данных из буфера и размещения в соответствующих полях в специфичном для платформы виде. Может быть это не так «просто» и «изящно» выглядит, зато надёжно, переносимо и расширяемо.
std::static_pointer_cast с r-value в качестве параметра — не по стандарту. По крайней мере, документ за номером N3242 такой специализации не специфицирует. Может быть просто забыли, может быть были какие-то глубокие причины.
Сдаётся мне, что проблема тут не в финальном std::move (его наличии или отсутствии), а в том, что boost::static_pointer_cast (впрочем, как и std::static_pointer_cast) получает свой аргумент по обычной (а не r-value) ссылке. Отсюда и щёлканье счётчиком. Т. е. move-семантика тут (по логике вещей) и не должна работать. Есть предположение (которая подтвердила проверка на компиляторе), что код без static_pointer_cast'а бдут работать так, как ожидает автор — никаких lock xadd не выполняется. Проверялось на таком коде:
class BaseClass
{
public:
virtual ~BaseClass() {;}
Потому что на Qt только часть часть проекта. Использовать Qt только для пропертей считаю не очень хорошей мыслью. Тем более, что взаимодействовать с Qt-свойствами всё равно надо через сеттеры и геттеры.
По поводу нанораспилов, нанобюджетов и прочих «нано» говорить не возьмусь — недостаточно данных для вынесения того или иного суждения. Но вот судя по комментариям — специалистов по подсчёту денег в чужих карманах у нас уже достаточно.
Intel — спасибо за конференцию, и за поддержку науки. Чтобы, как говориться, не в последний раз. :)
Если после нажатия «Выход» в профиле и перед фактическим выходом из приложения отметить галку «Автоматический логин» на стартовом скрине, то в следующий раз он сам залогиниться.
Итого, по здравым калькуляциям получается:
— 300 руб. за городскую линию для экстренных вызовов (хотел бы я посмотреть на американского провайдера IP-телефонии, понимающего простой короткий русский номер 03)
— Ещё 100 рублей в месяц (те самые 40$/год по текущему курсу) — за IP-телефонию;
— Ещё, мммм… Положим 300 рублей в месяц за интернет-канал;
— И рублей 150 за постоянно включённый комп, обеспечивающий всю эту красотень под названием «часами со знакомой из Владивостока через спичечную коробочку».
Амортизацию всего этого добра в расчёт не берем.
В сухом остатке — 850 руб/мес. За возможность часами болтать по IP-телефону с канадским номером… Для пенсионера.
Уточняющий вопрос. А интернет в квартирах пенсионеров откуда возьмётся? И, допустим, в Москве он уже дешёвый (сравнительно). А вот где-нибудь на Сахалине — уже нет. И какие будут тарифы, если, положим, пенсионерка захочет с этого же телефона позвонить на городской? А если ей захотят позвонить с городского? Платить «любимому Связьинвесту» по международным тарифам?
Мне кажется, что если клиент хочет взять ответственность за сохранность своих средств на себя — ему не стоит нести свои деньги в банк. Он может воспользоваться любой из доступных сейчас электронных платёжных систем, подобрать удобный для себя пароль из двух-трёх цифр, и полностью и самостоятельно нести ответственность за такого рода действия.
Протокол обмена — это, обычно, хорошо стандартизированная и описанная штука. И данные, которые ходят по этому протоколу, совсем не обязательно должны «ложиться» на их бинарное представление в памяти. Более того, то, что они в данном конкретном случае ложатся — это большое везение. :) По этому при получении данных их таки лучше разобрать «ручками», и разложить по полям структуры, чем играть в рулетку и надеяться на то, что авось повезёт, и данные в память лягут так, как надо.
Спасаться от лишнего паддинга можно и без pragma pack. Рецепт прост — поля в структуре «сортируются» по размеру. В начале помещаются самые большие (uint64, uint32), в конце — самые маленькие — (uint8). Все вопросы с порядком байт должны (на мой взгляд) решаться в точке сериализации и десериализации данных (ну, например, при отправке в сеть и получения из сети), а сам этот процесс, по хорошему, должен производиться не сразу в структуру, а путём последовательного чтения данных из буфера и размещения в соответствующих полях в специфичном для платформы виде. Может быть это не так «просто» и «изящно» выглядит, зато надёжно, переносимо и расширяемо.
boost::shared_ptr<BaseClass> MakeSharedPtr()
{
boost::shared_ptr<BaseClass> ptr = boost::make_shared<DerivedClass>();
return ptr;
}
class BaseClass
{
public:
virtual ~BaseClass() {;}
void Foo()
{
std::cout << «Foo called» << std::endl;
}
};
class DerivedClass: public BaseClass
{
public:
};
boost::shared_ptr MakeSharedPtr()
{
boost::shared_ptr ptr = boost::make_shared();
return ptr;
}
int main()
{
auto ptr = MakeSharedPtr();
ptr->Foo();
}
При добавлении в этот код boost::static_pointer_cast'а всё начинает работать именно так, как описано топикстартером.
class FullStrategyMapScene : public QGraphicsScene
{
Q_OBJECT;
public:
// Инициализируем свойства
FullStrategyMapScene() : properties(this) {;}
~FullStrategyMapScene();
// Объявляем свойства
PROPERTIES(FullStrategyMapScene,
// Простое свойство
PROPERTY(QSize, CellSize)
// Простое свойство с инициализацией
PROPERTY_I(Unit const*, CurrentUnit, NULL)
// Свойство с геттером и сеттером
RW_PROPERTY(QPoint, CursorPos, GetCursorPos, SetCursorPos)
// Свойство с сеттером
WO_PROPERTY(IPlanet const*, Planet, SetPlanet)
RO_PROPERTY(ISurfaceMap const*, SurfaceMap, GetSurfaceMap)
);
private:
void SetPlanet(IPlanet const* planet);
QPoint const& GetCursorPos() const;
void SetCursorPos(QPoint const& pos);
ISurfaceMap const* GetSurfaceMap() const;
};
Тоже не бог весть что, но позволяет достигнуть желаемого эффекта («описания полей класса с контролируемым доступом»).
Intel — спасибо за конференцию, и за поддержку науки. Чтобы, как говориться, не в последний раз. :)
— 300 руб. за городскую линию для экстренных вызовов (хотел бы я посмотреть на американского провайдера IP-телефонии, понимающего простой короткий русский номер 03)
— Ещё 100 рублей в месяц (те самые 40$/год по текущему курсу) — за IP-телефонию;
— Ещё, мммм… Положим 300 рублей в месяц за интернет-канал;
— И рублей 150 за постоянно включённый комп, обеспечивающий всю эту красотень под названием «часами со знакомой из Владивостока через спичечную коробочку».
Амортизацию всего этого добра в расчёт не берем.
В сухом остатке — 850 руб/мес. За возможность часами болтать по IP-телефону с канадским номером… Для пенсионера.