LINUX.ORG.RU

#pragma once


0

1

Я являюсь адептом #pragma once, использую эту директиву во всех своих проектах и поощряю других к тому же. Тем не менее время от времени приходится натыкаться на код с использованием header guards, причём код относительно свежий, без налёта 20-го века. Сей факт меня, как представителя homo sapience (с акцентом на sapience) не перестаёт удивлять.

Я честно поднял для себя этот вопрос, попытался проанализировать, что же движет программистами обоих кланов. Список достоинств и недостатков обоих методов получился примерно следующим:

1. header guards - это хак и как любому хаку в коде ему не место. Более того, это хак в квадрате из-за использования макросов, что сами по себе есть зло. Логика подсказывает, что если же хак превращается в правило - проблему нужно решать на глобальном уровне, причём стандарт должен минимизировать побочные эффекты к нулю. Именно отсюда и родился #pragma once - тот самый стандарт, призванный решить существовавшие проблемы с включением заголовочников.

2. Конфликт имён. Если вы в своём коде добавили util.h с #define UTIL_H внутри, рано или поздно вы наткнётесь на конфликт с 3rdparty-библиотекой с таким же макросом. Единые правила для выбора имён макросов дискредитируют саму их идею - если все будут их придерживаться, то в результате они породят те же конфликты. Остаётся надеяться на генераторы мусорных суффиксов, которые а) идут вразрез с идеей того, что код должен писаться для человека и б) привет, рефакторинг! то-есть, пока... переименовав один заголовочник в другой или просто скопировав код получаем чёрти что.

3. Поощрение к хитростям. Если макрос объявлен, значит его можно и удалить, чтобы потом попробовать включить заголовочник снова. Или смешная до коликов в животе попытка «ускорить» компиляцию следующим хаком:

#ifndef UTIL_H
#include "util.h"
#endif

Которая не только ни на грамм не быстрее, но ещё и вынуждает следить по всему коду, чтобы макрос совпадал.

Конечно подкованный кодер к подобным хитростям чужд, максимум кого ими можно обхитрить - самого себя. Тем не менее неоднозначная семантика header guards вынуждает молодого программиста задуматься - а вдруг таки можно? Однозначная семантика #pragma once решает эту проблему на корню, минимизируя возможные хаки и ошибки к нулю.

4. Распространённость и поддержка компиляторами. Как известно, чем проще код - тем легче его сопровождать. Аргумент сложности реализации #pragma once для меня вообще смешон, поддержка реализуется примерно следующим алгоритмом:

int include_or_not_the_header( const char * path )
{
    if ( pragma_onced_headers_cache_contains( path ) )
        return DONT_INCLUDE_THIS_HEADER;

    if ( does_header_contain_pragma_once( path ) )
        pragma_onced_headers_cache_add( path );
    
    return INCLUDE_THIS_HEADER_PLEASE;
}

Если кто сможет назвать хоть один компилятор (помимо мирно лежащих в гробах) без поддержки #pragma once - будьте добры. Мой гугл находит только кивания, что суслик как бы есть, но в глаза его никто не видел.

5. Миф о проблемах с символическими ссылками в #pragma once. Давно развеян с тех пор, как в GCC в кеш (см. пример выше) стали ложить не символические ссылки на файлы, а сами файлы.

6. Достоинства header guards. Здесь прочерк.

Итого я пришёл к выводу, что header guards продолжают пользоваться:
1) Осознанно. Бородатые программисты с бородатыми компиляторами со специфичным кодом под специфичные устройства.
2) Неосознанно - все остальные.

Отчасти на пункт 2 повлияли два фактора - ISO и GCC. Первый, насколько я понимаю, до сих пор жмётся, чтобы добавить директиву в стандарт. Второй долгое время выдавал warning на эту директиву, мол deprecated и вообще ай-яй-яй. Пользователи при этом балансировали на грани, а многие поддались общей панике и устроили крестовые походы набеги на #pragma once, насаждая всюду религию header guards. И видимо по инерции не заметили, как ещё в 2004-м году (!!) в GCC 3.4 официально убрали любые комплексы по этому поводу, оставив #pragma once навсегда в списке поддерживаемых директив.

Аргументы за и против, а также список компиляторов без поддержки #pragma once - приветствуются. Примеры сотен кода, в которых используются header guards без аргументации почему - можете оставить себе.

★★★★★

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

unC0Rr ★★★★★
()

Ну в 2005 года MSVC работал с ним. но криво

namezys ★★★★
()

Если уж вставать на тропу войны с бородатыми программистами, то тогда вообще никакой #pragma once не надо. Зачем она нужна? Пишу #include <bla-bla-bla.h> и всё. Почему вы хотите меня заставить писать какую-то прагму once, до которой мне вообще нет дела? Компилятор сам не может разобраться?

anonymous
()

По моему «ложить» - это нецензурщина. есть такое слово мужеложец например. Говорить «класс А ложит что-то в класс В» это, извините, х*ня какая-то получается и если вы пишете что, что-то там «ложит» куда-то там, это всё равно, что «еб**ий класс А еб*т класс В». Ну а эти ваши споры о том, что это вроде как правомерно в данном случае, выставляют вас в дурном свете. Будь я на вашем месте, обязательно исправил бы на «кладёт». Ну а по сабжу, что быстрее p++ или ++p ?

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

> Если уж вставать на тропу войны с бородатыми программистами, то тогда вообще никакой #pragma once не надо. Зачем она нужна? Пишу #include <bla-bla-bla.h> и всё.

Поведение #include закреплено в стандарте. А то о чём вы говорите называется #import. Более того, #import и отсутствие каких-либо механизмов двойного включения заголовочников - стандарт кодирования в Obj-C.

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

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

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

Ну тогда получается, что эта прагма вообще не нужна. Нужна или классика по include или новое в стиле import. А pragma once это какой-то непонятный промежуточный между include и import элемент.

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

ложить и ложиться - разные вещи. Второе - культурное слово. И значить «ложиться спать» вполне так ничего. Но «ложи (себя) спать» уже как-то неграмотно.

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

> ложить и ложиться - разные вещи.

А «клеить» и «клеиться», «лить» и «литься», «омывать» и «омываться»? И ещё 100500 глаголов, как быть с ними, тоже все нецензурные? Как так вышло, что самому можно «ложиться спать», но «ложить спать ребёнка» - брань? Ребёнка нельзя «класть», он не мешок с конфетами. «Уложить» тоже не подходит, вы же с ним не боролись. «Укладывать» - несовершенный глагол, имеет другой смысл. Получается из языка вырезали слово, а замену ему не придумали, где логика?

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

не «ложить спать», а «положить спать». Или, если нужен текущий процесс показать, то «укладывать спать»

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

Озеленение - нормальное слово. Но совсем нельзя сказать «осерение», имея в виду серый цвет. Так что действия «по аналогии» неуместы, язык - это язык, а не математика.

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

Даже если так говорила ваша мама (при всём моём уважении к ней), это не означает, что так правильно. «ложить спать», «ложись спать» - это тоже не правильно.

anonymous
()

> Первый, насколько я понимаю, до сих пор жмётся, чтобы добавить директиву в стандарт.

пипец. Прагмы не могут быть стандартизованы by design. Чтобы их стандартизировали нужно чтобы все его авторы 9-го градуса вымерли, а новых пионеров понабрали.

Подробнее: http://www.rsdn.ru/forum/cpp/3979885.flat.aspx

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

> Прагмы не могут быть стандартизованы by design.

Да-да, спасибо, я плохо выразился. Скажем так, сделать аналогичную директиву и включить её в стандарт. Хотя через столько лет поезд всё дальше и дальше, а в затылок уже дышит C++0x. Думаю, все останутся при своих и стоит просто пользоваться #pragma once как есть.

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

>>пипец. Прагмы не могут быть стандартизованы by design

Почему? Единственное, что я вижу - это будет противоречие старого стандарта и нового. Если старого бы не было, что мешает стандартизовать?

alex_custov ★★★★★
()

Если чо, grep и sed разрешат конфликты.

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

>А вот если сделать поверх с++ какой-то язык, по семантике не сильно от него отличающийся, но дающий возможность запрещать простреливание ног (с возможностью разрешать это в отдельных файлах) и писать покороче и пояснее — тогда да.

Этот язык называется D

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

> Почему? Единственное, что я вижу - это будет противоречие старого стандарта и нового. Если старого бы не было, что мешает стандартизовать?

да, я сейчас понял, что стандартизованные прагмы уже есть:) Правда, они все начинаются на #pragma STDC ....

В любом случае, #pragma once это «неправильная» прагма. Все правильные прагмы всего лишь меняют детали поведения, но если убрать прагму, то код все равно остается корректным. Неправильные прагмы этим свойством не обладают — если неправильную прагму убрать, то код может превратиться в говно.

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

А то о чём вы говорите называется #import.

Тут уже говорили, что #import в Visual C++ означает совсем другое. #import в C или C++ непереносим дальше GCC (clang?).

Begemoth ★★★★★
()

[лицорука.жпг][травмы и разрывы]

>homo sapience c акцентом

Акцент такой заметный, слюшай да! Человеки разумные обычно относятся к виду Homo Sapiens, потому что латынь. И да, некоторые, особо акцентированные, относят себя к Homo Sapiens Sapiens, потому что ЧСВ^Wхотят отличаться от кроманьонцев.

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

>Использование «положить» и «класть» в русском языке неоднозначно, фактически это одно слово с двумя корнями, причём второе больше похоже на паразит. Я понимаю, что вы блюдёте за чистоту языка, но шанс ошибиться при использовании этого слова зашкаливает.

Вот прежде чем писать неоднозначные темы, загляни в справочник «Управление в русском языке» или «Трудности русского языка». Там тебе подробно распишут, почему ты не прав, когда пишешь «ложить» и «блюдете за чистоту»

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

Случайно или намеренно путаешь просторечие, допустимое в разговоре (если никто не слышит) и нормативный письменный язык, о чем еще говорить?

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

>нормативный письменный язык

наверное, вы хотели сказать «нормативный литературный язык».

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

Наверное не хотел. Нормативный и литературный в одном словосочетании как-то тавтологично, наверное. (И да, письменный ненормативный встречается в интернетах часто - наверное, хотел обособить от него.)

slackwarrior ★★★★★
()
Ответ на: [лицорука.жпг][травмы и разрывы] от slackwarrior

> Акцент такой заметный, слюшай да!

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

«Трудности русского языка»


Вы знаете, у меня, как и у большинства русскоязычного населения, трудностей с глаголом «ложить» нет. Есть разве что батхёрт у некоей элиты, ратующей за мнимую чистоту языка, но, в свою очередь, логически объяснить которую они не в состоянии. И это вызывает у них ещё больший батхёрт, переходящий в перманентное состояние.

Все эти правила пишутся людьми. И когда кто-то пытается сказать, что «лить-полить» есть, «сеять-посеять» тоже есть, а «ложить-положить» мы заменим на «класть-положить» - у любого здравомыслящего человека это вызовет закономерный вопрос: «с какого вдруг перепугу?». Более того, на этих людей будут смотреть как на второй сорт, как будто это правило должно впитываться с молоком матери.

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

«Опрощайтеся!» (с)

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

Есть такой древний боян, примерно Троянской войны^WДиона Хрисостома ровесник http://myriobiblion.byzantion.ru/dion/Dion-XVIII.htm tl;dr для Ъ: «То немногое, что люди знают, они знают благодаря учению» (с) Причем тут молоко матери? В C++, говорят, goto есть, о ужас, но никто вас не заставляет им пользоваться. (Одепты в тред - гоп!) Англосаксы с языком поступили здорово: некоторые не знают, что в английском есть^Wбыло местоимение «ты», «флексии» и прочие наклонения. Так давно не пользовались. А зачем - бэйсик инглиш-то осилить легче... И нужнее: на фирме вон спец курс пиджин-инглиша для болтовни с индусами ввели. Ынтерпрайз уравняет всех: нужно много и попроще.

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

Можно долго рассказывать про обучение. Но факт остаётся в том, что слова «лежать», «ложить», «лежит», «положить», «ложись», «ложишься», «ложи» - естественны, созвучны и логичны для русской речи. Более того - все они существуют в русском языке и лексиконе и имею недвусмысленные значения. Именно поэтому попытка любая поделить людей на сорта по признаку использования этих слов будет обречена на провал. Потому что в удалении конкретных слов из языка отсутствует какой-либо смысл, понятный всем. Считайте, что это русское народное слово.

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

>Считайте, что это русское народное слово.

Говорить от имени народа - это так скромно и веско. :) «Грамотный» и «неграмотный» - тоже слишком однозначные слова. (Более однозначное только «беременная».) В них какой-то граммар-нацистский максимализм и нетерпимость. «Полуграмотный» и «почти грамотный» - как-то неполиткорректно. «Лицо с языковыми затруднениями» - это непонятно, потому необидно. Наверное, как-то так.

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

А ещё есть слова «х.й» и «пи.да». Эти слова естественны, созвучны и логичны для русской речи. Более того - все они существуют в русском языке и лексиконе и имею недвусмысленные значения. Именно поэтому попытка любая поделить людей на сорта по признаку использования этих слов будет обречена на провал.

Поэтому даёшь свободу! Что естественно, то небезобразно!

Вы это имеет в виду?

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

> Вы это имеет в виду?

Отнюдь. Мне наоборот, больше жаль слова «голубой», «член», «трахать», которые из невинных шагнули на грань ругательных.

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

Стандарт гласит, что #pragma нужно для не стандартных расширений. То, что оно прижилось ещё не повод добавлять это в стандарт.

Вот если бы оно было просто #once, то пропихнуть было бы проще. Такие дела

// делаю header guards дабы избежать ЛЮБОЙ головной боли ГАРАНТИРОВАННО.

ssvda
()

В одно время, когда задавался таким вопросом выяснил, что ни header guards ни pragma once полностью не могут исключить некоторые случаи. Поэтому лучше всего использовать их одновременно. Но т.к. это только усложняется, да и могут возникнуть проблемы с pragma once, решил что header guards меньшее из зол.

Zodd ★★★★★
()

использую #pragma once, потому-что смотрится аккуратней

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

— Клад — это то, что покладено? — Не покладено, а положено! — Не положено, а закопано! — Не закопано, а зарыто!

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

«ложить спать» (кого-то) - неправильно. «класть спать»

Ложись спать - правильно. Возвратная форма (сь)

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

> мнимую чистоту языка
Детектор мнимости в студию.

логически объяснить которую они не в состоянии

Первый признак лингвистической неграмотности - убежденность, что язык 100% подчиняется логике.

«Сол, фасол, антресол пишется с мягкий знак. Вилька, булька, бутылька - без мягкий знак. Это невозможно понять, это нужно запомнить!»

у любого здравомыслящего человека это вызовет закономерный вопрос: «с какого вдруг перепугу?»

Здравомыслящий человек - это тот, который понимает, что для языка единственное реальное объяснение «исторически сложилось».

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

Отнюдь. С чтением хорошей художественной литературы, написанной хорошим русским языком. Причем - лошадиными дозами. Хотя, конечно, когда родители дома говорят на хорошем языке - оно впитывается практически с молоком матери.

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

> Именно поэтому попытка любая поделить людей на сорта по признаку использования этих слов будет обречена на провал.
Ви таки будете смеяться, но подобное «определение уровня грамотности» происходит довольно быстро, достаточно с человеком поговорить пару минут. Глакол «ложить» редко ходит один.

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

(=

Когда я работал в одной «gamedev»...кхм...конторке, которая разрабатывала игры, был у нас очень хороший программист. Он был очень хороший: быстро разрабатывал и внедрял «feature»...кхм...новинки, после чего мы неделями ругались на «спагетти-код» и выискивали в его хорошем слабо документированном коде неправильно использованные «copy-paste». Но это отдельная история.

Так вот. Он говорил ложИть, покласть, а иногда даже лОжить. Мы ему советовали использовать более современные версии слов. Действительно, «ложит по адресу» звучало как-то ... архаично что ли.

А потом позже я понял, что это всё из-за родителей. Мама с папой преподаватели, а это «ложит» был слабый и невинный протест.

Ещё раз повторюсь: автору темы нечем заняться. Рисование мелками или полицветами и то принесёт ему большее моральное удовлетворение. =)

m4n71k0r
()
Ответ на: (= от m4n71k0r

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

автору темы нечем заняться


Спасибо за ваше мнение. Само чтение ЛОРа, а тем более участие в дискуссиях, есть доказательство того, что заняться больше нечем. Но мы ведь не пишем это в каждом посте, верно?

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

Во-первых, ты ... и ......

Во-вторых разница между вариантами не велика, а следовать стандарту все же хорошо.

В-третьих, если и менять что-то, то сразу делать полноценную систему модулей, а не один костыль заменять другим.

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

>Вы знаете, у меня, как и у большинства русскоязычного населения, трудностей с глаголом «ложить» нет. Есть разве что батхёрт у некоей элиты, ратующей за мнимую чистоту языка, но, в свою очередь, логически объяснить которую они не в состоянии. И это вызывает у них ещё больший батхёрт, переходящий в перманентное состояние.

Мухаха, вопросов больше нет =). У большинства русскоязычного населения «ложить» вызывает резкое вздергивание где-то там глубоко в мозгу.

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

Текущий стандарт C++ доживает своё, на смену ему приходят C++0x и D, в которых много нововведений. Здесь речь именно о том, стоит ли использовать #pragma once для текущей редакции C++. Все компиляторы что я знаю имеют поддержку этой директивы, новых компиляторов, на 100% реализующих стандарт, не предвидится, язык для этого слишком сложен. Влияния стандарта на конкретно эту директиву в существующих компиляторах нет, скорее другие компиляторы будут ориентироваться на совместимость с GCC/MSVC/Clang. Кстати на счёт последнего, сейчас доберусь до работы, проверю как он себя ведёт.

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

>Мухаха, вопросов больше нет =). У большинства русскоязычного населения «ложить» вызывает резкое вздергивание где-то там глубоко в мозгу.

«ложить» вызывает резкое вздергивание где-то там глубоко в мозгу.

вызывает резкое вздергивание где-то там глубоко

Язык нестабилен. Он постоянно эволюционирует. Граммарнаци срут кирпичами. Это естественный процесс.

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

> В-третьих, если и менять что-то, то сразу делать полноценную систему модулей, а не один костыль заменять другим.

вот-вот

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

(=

Вы как-то в корне поверхностно воспринимаете =)

Заканчивайте уже продолжать =)

Никто не против #pragma once =)

Мне больше неприятно то, что msvc поддерживает использование почти любых символов в именовании идентификаторов (как же адски сложно разбирать случайно попавший тебе в руки китайский код =) ). Также неприятно то что разработчики компиляторов C++ позволяют себе вольность использовать стандарт C. В g++ можно указывать размер массива переменной ( а это уже C99 ), например. Считаю, если есть стандарт, то следуйте ему. Не нравится - обращайтесь в комитет. Пишите письма. Собирайте подписи. Навязывание - зло. Это-то поймите. Вот к чему я веду.

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

=)

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

>То-есть по-вашему однозначно правильными будут вторые варианты? 1. Класс А положил в класс Б значение. 2. Класс А поклал в класс Б значение. 1. Значение лежит в классе А. 2. Значение покладено в классе А.

You made my day

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