Здравствуйте, igna, Вы писали:
V>>что ifdef вернёт false I>На это никто не полагается, полагаются на то, что ifdef вернёт true внутри функции.
макрос должен быть определён или неопределён до стадии препроцессора, там не никаких функций ещё
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, rg45, Вы писали:
R>Несложные эксперименты в Visual Studio показывают, что все так и есть. __FUNCSIG__ — хитрый такой макрос, который определен как __FSTREXP __FUNCSIG__ (__FSTREXP — пустое макроопределение). Его нельзя ни переопределить, ни отменить. И, как видно, "валиден" и "определен"- не одно и то же — студия позволяет использовать __FUNCSIG__ в других директивах (в т.ч. и для определения других макросов). Но при попытке развернуть его до строкового значения вне функции вызывает ошибку компиляции: "'__FUNCSIG__': predefined macro cannot appear outside of a function body".
На всякий случай хочу заметить, что из этих экспериментов не следует, что __FUNCSIG__документированно определен вне функции.
Здравствуйте, igna, Вы писали:
I>Здравствуйте, Vain, Вы писали: V>>тем не менее ifdef возвращает true, проверено в 2005/2010 студиях
I>Ну неудивительно, что разработчики Boost не полагаются на недокументированное поведение компилятора.
Есть еще одно соображение. Почему разработчики в качестве аргумента условной директивы использовали именно __FUNCSIG__, а не какой-нибудь другой специфический макрос — _MSC_VER, например? Возможно, __FUNCSIG__ используется не только в MSVC, а в каких-то еще компиляторах? И если так, то решение о месте размещения всего этого хозяйства не могло приниматься только лишь на основании поведения MSVC.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, Nikita.Trophimov, Вы писали:
NT>С чего бы? Это же макрос, на самом деле __FUNCSIG__ как раз и будет помещён в функцию.
Проверить, будет ли __FUNCSIG__ определен внутри функции, можно только внутри функции. Слово "функция" в предыдущем предложении встречается два раза и относится к двум различным функциям, в первом случае — к той, где BOOST_CURRENT_FUNCTION используется, во втором — к той, где он определяется.
То есть __FUNCSIG__ исполняет в реализации две роли, ту же, которую исполняет __GNUC__, и ту же, которую исполняет __PRETTY_FUNCTION__. Но чтобы __FUNCSIG__ можно было использовать как __GNUC__, его нужно поместить во (вспомогательную) функцию.
Здравствуйте, igna, Вы писали:
I>То есть __FUNCSIG__ исполняет в реализации две роли, ту же, которую исполняет __GNUC__, и ту же, которую исполняет __PRETTY_FUNCTION__. Но чтобы __FUNCSIG__ можно было использовать как __GNUC__, его нужно поместить во (вспомогательную) функцию.
в 2005 студии не нужно
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, Vain, Вы писали:
V>Здравствуйте, igna, Вы писали:
I>>То есть __FUNCSIG__ исполняет в реализации две роли, ту же, которую исполняет __GNUC__, и ту же, которую исполняет __PRETTY_FUNCTION__. Но чтобы __FUNCSIG__ можно было использовать как __GNUC__, его нужно поместить во (вспомогательную) функцию. V>в 2005 студии не нужно
R>Ты знаешь способ вынести этот фрагмент из определения функции?
Компилятор мог бы определять __FUNCSIG__ вне функции как-нибудь. Фактически только для того, чтобы можно было проверить, что этот макрос поддерживается.
Здравствуйте, rg45, Вы писали:
I>>>То есть __FUNCSIG__ исполняет в реализации две роли, ту же, которую исполняет __GNUC__, и ту же, которую исполняет __PRETTY_FUNCTION__. Но чтобы __FUNCSIG__ можно было использовать как __GNUC__, его нужно поместить во (вспомогательную) функцию. V>>в 2005 студии не нужно R>
I>То есть __FUNCSIG__ исполняет в реализации две роли, ту же, которую исполняет __GNUC__, и ту же, которую исполняет __PRETTY_FUNCTION__. Но чтобы __FUNCSIG__ можно было использовать как __GNUC__, его нужно поместить во (вспомогательную) функцию.
Т.е. даже просто для того, чтобы проверить, определён ли макрос __FUNCSIG__ при помощи препроцессорной директивы #ifdef, нам нужна функция?
Здравствуйте, igna, Вы писали:
V>>тем не менее ifdef возвращает true, проверено в 2005/2010 студиях I>Ну неудивительно, что разработчики Boost не полагаются на недокументированное поведение компилятора.
непонятно зачем полагаться на поведение которого нет, в этом и был вопрос топикстартера, ваш кеп
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, Nikita.Trophimov, Вы писали:
NT>Т.е. даже просто для того, чтобы проверить, определён ли макрос __FUNCSIG__ при помощи препроцессорной директивы #ifdef, нам нужна функция?
В документации написано "Valid only within a function", так-что если не хочешь полагаться на недокументированное поведение компилятора, то да, нужна функция.
Здравствуйте, igna, Вы писали:
V>>непонятно зачем полагаться на поведение которого нет, в этом и был вопрос топикстартера, ваш кеп I>Это какого поведения нет?
что ifdef вернёт false
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, igna, Вы писали:
NT>>Т.е. даже просто для того, чтобы проверить, определён ли макрос __FUNCSIG__ при помощи препроцессорной директивы #ifdef, нам нужна функция? I>В документации написано "Valid only within a function", так-что если не хочешь полагаться на недокументированное поведение компилятора, то да, нужна функция.
почему недокументированное? все встроенные макросы должны быть определены до стадии препроцессора.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, Vain, Вы писали:
V>что ifdef вернёт false
На это никто не полагается, полагаются на то, что ifdef вернёт true внутри функции.
Компилятор может одно из трех:
— дать гарантию, что макрос определен внутри функции;
— дать гарантию, что макрос не определен внутри функции;
— не давать никакой из этих двух гарантий.
Кроме того он может одно из трех:
— дать гарантию, что макрос определен вне функции;
— дать гарантию, что макрос не определен вне функции;
— не давать никакой из этих двух гарантий.
Всего имеем 9 возможных комбинаций, VC++ согласно документации:
— дает гарантию, что __FUNCSIG__ определен внутри функции;
— не дает никакой гарантии по поводу определенности __FUNCSIG__ вне функции.
Поэтому надежно использовать его можно только внутри функции.
Здравствуйте, igna, Вы писали:
V>>почему недокументированное? все встроенные макросы должны быть определены до стадии препроцессора. I>А это что означает: "Valid only within a function"?
видимо символ __FUNCSIG__ будет заменён на стадии компиляции а не процессора?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, Vain, Вы писали:
V>видимо символ __FUNCSIG__ будет заменён на стадии компиляции а не процессора?
То есть, вне функции __FUNCSIG__ определен, но недействителен?
Можно и так понять, что __FUNCSIG__ определен как что-то вроде:
#define __FUNCSIG__ __funcsig__
А __funcsig__ в свою очередь как (статическая) константная переменная внутри функции.
Но я б на это не полагался, документация оставляет вопрос открытым, определен ли __FUNCSIG__ вне функции. Нет же в стандарте ограничения, что любой нестандартный предопределенный макрос должен быть либо не определен, либо определен везде.
Здравствуйте, Vain, Вы писали:
V>макрос должен быть определён или неопределён до стадии препроцессора, там не никаких функций ещё
Где такое написано? По крайней мере есть __FILE__ и __LINE__, которые хоть и определены везде, но меняют значение. Это конечно не одно и тоже, переопределить макрос и "разопределить" его, но достаточно близкие вещи. Если компилятору вздумается поиметь предопределенный макрос, определенный не везде, стандарту это противоречит не будет.
Здравствуйте, igna, Вы писали:
I>Компилятор может одно из трех:
А какая связь между препроцессором (который поддерживает #ifdef и #define) и функцией? Ведь препроцессор не знает, где он сейчас — в глобальном пространстве, классе или функции.
ЗЫ: по стандарту __func__ & K° должы быть эквивалентны const char __current_function[], насколько я помню, то есть, мы можем сказать, что __func__ доступен где угодно (как обычный #define something), но не определён (к примеру, вне функции там будет "\0".
Так как же реализуется поддержка #ifdef (или #if ?) на уровне препроцессора?
Здравствуйте, igna, Вы писали:
I>>>А это что означает: "Valid only within a function"?
V>>видимо символ __FUNCSIG__ будет заменён на стадии компиляции а не процессора?
I>То есть, вне функции __FUNCSIG__ определен, но недействителен? I>Можно и так понять, что __FUNCSIG__ определен как что-то вроде:
I>
I>#define __FUNCSIG__ __funcsig__
I>
I>А __funcsig__ в свою очередь как (статическая) константная переменная внутри функции.
Несложные эксперименты в Visual Studio показывают, что все так и есть. __FUNCSIG__ — хитрый такой макрос, который определен как __FSTREXP __FUNCSIG__ (__FSTREXP — пустое макроопределение). Его нельзя ни переопределить, ни отменить. И, как видно, "валиден" и "определен"- не одно и то же — студия позволяет использовать __FUNCSIG__ в других директивах (в т.ч. и для определения других макросов). Но при попытке развернуть его до строкового значения вне функции вызывает ошибку компиляции: "'__FUNCSIG__': predefined macro cannot appear outside of a function body".
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, igna, Вы писали:
I>Но я б на это не полагался, документация оставляет вопрос открытым, определен ли __FUNCSIG__ вне функции. Нет же в стандарте ограничения, что любой нестандартный предопределенный макрос должен быть либо не определен, либо определен везде.
тогда бы компилятор не смог скомпилировать свой же отпроцешшеный код
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, igna, Вы писали:
V>>макрос должен быть определён или неопределён до стадии препроцессора, там не никаких функций ещё I>Где такое написано? По крайней мере есть __FILE__ и __LINE__, которые хоть и определены везде, но меняют значение. Это конечно не одно и тоже, переопределить макрос и "разопределить" его, но достаточно близкие вещи. Если компилятору вздумается поиметь предопределенный макрос, определенный не везде, стандарту это противоречит не будет.
незнаю на счёт стандарта, но думаю стейджы определены де факто: сначало препроцессор, потом компилятор с линкером
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, igna, Вы писали:
I>На всякий случай хочу заметить, что из этих экспериментов не следует, что __FUNCSIG__документированно определен вне функции.
но и того что это распространяется на ifdef тоже не следует
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, igna, Вы писали:
I>Где такое написано? По крайней мере есть __FILE__ и __LINE__, которые хоть и определены везде, но меняют значение. Это конечно не одно и тоже, переопределить макрос и "разопределить" его, но достаточно близкие вещи. Если компилятору вздумается поиметь предопределенный макрос, определенный не везде, стандарту это противоречит не будет.
Тут есть проблемы с логической моделью.
Пока ты не проведёшь макроподстановки, ты не сможешь понять внутри ты определения функции находишься или нет, а пока не сможешь понять, не сможешь провести макроподстановки...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
I>А это что означает: "Valid only within a function"?
А это же разные вещи. Допустим, FUNCSIG определен только внутри функции (что автоматически значит, что он раскрывается не пре-процессором, а компилятором).
Но банальный #ifdef — то точно выполняется препроцессором!! И на этом этапе, если FUNCSIG еще не определен, то и ifdef вернет false.
Сами себя перехитрили.