signed bool test = -true; ///< MS VS watch кстати говорит, что test имеет тип int :xz:
И заработало
Народ, почему это заработало? Зачем вообще в С++ signed/unsigned для bool?
После такой находки пошел выпил чайку и сразу подумалось о перегрузке:
void foo( bool ){} ///< 1void foo( signed bool ){} ///< 2void foo( unsigned bool ){} ///< 3 - (а здесь MS VS watch видит unsigned int)
//void foo( unsigned int ){} ///< 4 - а вот если это откомментировать, то будет compiler-error - function already has bodyint main()
{
signed bool test = -true;
foo( test ); ///< 2
foo( false ); ///< 1
foo( unsigned bool( test ) ); ///< 3
}
Знает кто-нибудь нафига в С++ такие недо-типы? Это же еще хуже char, signed char, unsigned char. Если я верно понял, то signed и unsigned bool это typedef-ы соответственно:
typedef unsigned int unsigned bool;
typedef signed int signed bool;
Это умозаключение подтверждает тот факт, что на MS VS 2007.3 sizeof( unsigned int ) == sizeof( unsigned bool ) — true; sizeof( bool ) == sizeof( unsigned bool ) — false (прочем последний больше sizeof( bool ) в 4 раза).
Короче, прикольный язык С++ всегда есть что-то новое и непонятное (многие бы сказали бессмысленное ).
Здравствуйте, anonim_44ax, Вы писали:
_>Случайно написал: _>
_>signed bool test = -true; ///< MS VS watch кстати говорит, что test имеет тип int :xz:
_>
_>И заработало _>Народ, почему это заработало? Зачем вообще в С++ signed/unsigned для bool?
MSVS... там ещё и не то работает
На самом деле в стандарте 3.9.1.6 чётко прописано "there are no signed, unsigned, short or long bool types or values". Так что не заморачивайтесь это открытие -- скорее из разряда "баги", чем "фичи".
Здравствуйте, anonim_44ax, Вы писали:
_>Случайно написал: _>
_>signed bool test = -true; ///< MS VS watch кстати говорит, что test имеет тип int :xz:
_>
_>И заработало _>Народ, почему это заработало? Зачем вообще в С++ signed/unsigned для bool?
А почему ты решил, что в C++ они разрешены? См. п. 7.1.5.2 Simple type specifiers стандарта C++:
Table 7 summarizes the valid combinations of simple-type-specifiers and the types they specify.
Table 7—simple-type-specifiers and the types they specify
Specifier(s) | Type
-----------------------------------------
type-name | the type named
char | “char”
unsigned char | “unsigned char”
signed char | “signed char”
bool | “bool”
unsigned | “unsigned int”
unsigned int | “unsigned int”
signed | “int”
signed int | “int”
int | “int”
unsigned short int | “unsigned short int”
unsigned short | “unsigned short int”
unsigned long int | “unsigned long int”
unsigned long | “unsigned long int”
signed long int | “long int”
signed long | “long int”
long int | “long int”
long | “long int”
signed short int | “short int”
signed short | “short int”
short int | “short int”
short | “short int”
wchar_t | “wchar_t”
float | “float”
double | “double”
long double | “long double”
void | “void”
Re: Ух ё! signed/unsigned bool
От:
Аноним
Дата:
02.06.09 15:03
Оценка:
_>Знает кто-нибудь нафига в С++ такие недо-типы? Это же еще хуже char, signed char, unsigned char. Если я верно понял, то signed и unsigned bool это typedef-ы
ээээ.. а что плохого в signed/unsigned char? char — это ведь всего навсегда целочисленный тип sizeof которого всегда равен 1 Вас же не удивляет signed/unsigned int, signed/unsigned short. char от них ничем кроме sizeof а не отличается.
Чтобы лучше ощутить всю комичность ситуации написал супер-код:
signed void foo( unsigned bool b )
{
return signed void();
}
int main()
{
std::cout << foo( -true );
}
Сломал мозг пока пытался себе представить "знаковое и беззнаковое ничто"
Хотя вроде "правда с минусом" звучит более-менее логично (и значит пожалуй "неправда")
А>ээээ.. а что плохого в signed/unsigned char? char — это ведь всего навсегда целочисленный тип sizeof которого всегда равен 1
Неприятность с signed char, unsigned char и char заключается в том, что это три разных типа (которые между прочим участвуют в перегрузке), что не всегда очевидно.
Здравствуйте, anonim_44ax, Вы писали:
_>Случайно написал: _>
_>signed bool test = -true; ///< MS VS watch кстати говорит, что test имеет тип int :xz:
_>
_>И заработало _>Народ, почему это заработало? Зачем вообще в С++ signed/unsigned для bool?
_>После такой находки пошел выпил чайку и сразу подумалось о перегрузке: _>
_>void foo( bool ){} ///< 1
_>void foo( signed bool ){} ///< 2
_>void foo( unsigned bool ){} ///< 3 - (а здесь MS VS watch видит unsigned int)
_>//void foo( unsigned int ){} ///< 4 - а вот если это откомментировать, то будет compiler-error - function already has body
_>int main()
_>{
_> signed bool test = -true;
_> foo( test ); ///< 2
_> foo( false ); ///< 1
_> foo( unsigned bool( test ) ); ///< 3
_>}
_>
_>Знает кто-нибудь нафига в С++ такие недо-типы? Это же еще хуже char, signed char, unsigned char. Если я верно понял, то signed и unsigned bool это typedef-ы соответственно: _>
_>typedef unsigned int unsigned bool;
_>typedef signed int signed bool;
_>
_>Это умозаключение подтверждает тот факт, что на MS VS 2007.3 sizeof( unsigned int ) == sizeof( unsigned bool ) — true; sizeof( bool ) == sizeof( unsigned bool ) — false (прочем последний больше sizeof( bool ) в 4 раза).
_>Короче, прикольный язык С++ всегда есть что-то новое и непонятное (многие бы сказали бессмысленное ).
Под 2008 студией
sizeof( unsigned int ) == sizeof( unsigned bool )
sizeof( unsigned int ) == sizeof( unsigned double )
Самое удивительное — выскакивают ворнинги:
warning C4076: 'unsigned' : can not be used with type 'bool'
warning C4076: 'unsigned' : can not be used with type 'double'
Из МСДН-а:
Error Message:
'typemod' : can not be used with type 'typename'
A type modifier, whether it is signed or unsigned, cannot be used with a noninteger type. typemod is ignored.
Похоже не работает, "мелкомягкий" компайлер просто приводит эти типы к unsigned int!!!
_>Хотя вроде "правда с минусом" звучит более-менее логично (и значит пожалуй "неправда")
компилятора нет под рукой, но копчик мне подсказывает, что
true == -true
а также
-true == true
приняв во внимание, что с философской точки зрения false == -true, получаем:
false == -true == true -> false == true
как мы видим, MSVC++ активно участвует в улучшении нашей вселенной, упрощая фундаментальные основы и выходя на уровень абстракции, где не действуют законы логики
это компилируется или шутка такая?
Конечно шутка и конечно компилируется
Шутка потому, что использовать подобную "технику" программирования не имеет смысла.
Ну и по крайней мере на MS VS 2007.3 (нету другой под рукой) вполне успешно без карканья компилируется.
Здравствуйте, Ovl, Вы писали:
_>>Хотя вроде "правда с минусом" звучит более-менее логично (и значит пожалуй "неправда")
Ovl>компилятора нет под рукой, но копчик мне подсказывает, что Ovl>
true == -true
Ovl>а также
-true == true
Копчик не прав. Выражение -true имеет тип int, и его значение равно -1. Перед вычислением сравнения к операнду true будет применено интегральное продвижение — неявное преобразование к типу int (в данном случае), в итоге сравниваться будут два значения типа int, одно из которых равно -1, а другое — равно 1.
Здравствуйте, Masterkent, Вы писали:
M>Здравствуйте, Ovl, Вы писали:
_>>>Хотя вроде "правда с минусом" звучит более-менее логично (и значит пожалуй "неправда")
Ovl>>компилятора нет под рукой, но копчик мне подсказывает, что Ovl>>
M>true == -true
M>
Ovl>>а также M>
M>-true == true
M>
M>Копчик не прав. Выражение -true имеет тип int, и его значение равно -1. Перед вычислением сравнения к операнду true будет применено интегральное продвижение — неявное преобразование к типу int (в данном случае), в итоге сравниваться будут два значения типа int, одно из которых равно -1, а другое — равно 1.
копчик прав, просто глуп. потому что он имел ввиду равенство в смысле if(true) == if(-true)
Здравствуйте, ned, Вы писали:
ned>Здравствуйте, dmitry_npi, Вы писали:
_>>Последнюю строчку кто-то может объяснить?
ned>Декларация вызова функции. void игнорируется.
Да я понял, что функция, но как компилятор это вывел? Ведь signed void() — это вызов конструктора типа signed void, то есть это выражение, но не декларация функции. Этот же смысл был и впосте раньше, когда человек возвращал это выражение из функции.
(VC++ 2008)
Здравствуйте, anonim_44ax, Вы писали:
_>Случайно написал: _>
_>signed bool test = -true; ///< MS VS watch кстати говорит, что test имеет тип int :xz:
_>
_>И заработало _>Народ, почему это заработало? Зачем вообще в С++ signed/unsigned для bool?
Смею разочаровать получи весь листинг твоего кода и окажется, что ты где-то написал #define bool int
только по этому. В общем, MSVC достаточно хорошо следует стандарту (хотя как и многих компиляторов бываю свои бзынки). часто конструкция #define bool int встречается в допотопных библиотеках. Иногда эти самые дефайны весьма мерзкая штука (т.к. не позволяют отличать bool от int, что в C++ более чем важно бывает, ну а по сути bool и int весьма разные типы в частности если вспомнить operator bool, который бывает весьма к месту частенько (bool используется как тип к которому стандартно приводятся данные в if-ах while-ах for-ах, в то же время вполне может существовать operator int для целого представления класса и тут-то и начинается маразм, когда хорошо работавший код быстро ломается (а иногда компилятор даже и не ругается) только из-за одного мерзкого #define-а потому как бла-бла-бла)).
Здравствуйте, dmitry_npi, Вы писали:
ned>>Декларация вызова функции. void игнорируется. _>Да я понял, что функция, но как компилятор это вывел? Ведь signed void() — это вызов конструктора типа signed void, то есть это выражение, но не декларация функции. Этот же смысл был и впосте раньше, когда человек возвращал это выражение из функции.
Здравствуйте, klizardin, Вы писали:
K>Смею разочаровать получи весь листинг твоего кода и окажется, что ты где-то написал #define bool int
Что за чушь? В этом случае typeid выдаст int.
Здравствуйте, anonim_44ax, Вы писали:
_>Случайно написал: _>
_>signed bool test = -true; ///< MS VS watch кстати говорит, что test имеет тип int :xz:
_>
_>И заработало _>Народ, почему это заработало? Зачем вообще в С++ signed/unsigned для bool?
Эхх.. конечно же если выключать варнинги а также ставить минимальный уровень предупреждения от компилятора то ждут таких программеров открытия. при этом открытие того, что компилятор скомпилировал signed и проигнорировал дальнейший bool стало конечно же открытием, но будут и куда как более "приятные" открытия если отключать варниги.
читаем msdn.
Compiler Warning (level 1) C4076
Error Message
'typemod' : can not be used with type 'typename'
A type modifier, whether it is signed or unsigned, cannot be used with a noninteger type. typemod is ignored.
Здравствуйте, klizardin, Вы писали:
K>Эхх.. конечно же если выключать варнинги а также ставить минимальный уровень предупреждения от компилятора то ждут таких программеров открытия. при этом открытие того, что компилятор скомпилировал signed и проигнорировал дальнейший bool стало конечно же открытием, но будут и куда как более "приятные" открытия если отключать варниги.
Добрый MS-компилятор, который только погрозит пальчиком на, например, такое:
Здравствуйте, dmitry_npi, Вы писали:
d_n>Ведь signed void() — это вызов конструктора типа signed void
По стандарту этот код вообще незаконен. Выражение int() — это преобразование типа в функциональной нотации, где нет вызова какого-либо конструктора (int — встроенный тип, и у него нет конструктора).
d_n>то есть это выражение, но не декларация функции.
В коде
std::cout << typeid(int()).name() << std::endl;
int() — это не выражение и не объявление функции. Это тип (type-id) "функция без параметров, возвращающая int". Операндом typeid может быть как выражение, так и тип (см. 5.2.8). С другой стороны, int() может рассматриваться как выражение и как тип. Разрешение неоднозначности происходит согласно 8.2/2:
The ambiguity arising from the similarity between a function-style cast and a type-id can occur in different contexts. The ambiguity appears as a choice between a function-style cast expression and a declaration of a type. The resolution is that any construct that could possibly be a type-id in its syntactic context shall be considered a type-id.
т.е. в пользу интерпретации конструкции int() как типа, а не выражения.
Здравствуйте, anonim_44ax, Вы писали:
_>Случайно написал: _>
_>signed bool test = -true; ///< MS VS watch кстати говорит, что test имеет тип int :xz:
_>
_>И заработало _>Народ, почему это заработало? Зачем вообще в С++ signed/unsigned для bool?
signed unsigned определяют какие asm-овские команды использовать в арифметических выражениях. предполагаю мелкомягкие просто сделали это момент варнингом изначально по крайней мере найденной шестой студии этот варнинг присутствует, а потом не стали менять. это в большей степени связано с тем, что вообще-то и мелкомягкие частенько создавали версии до фиксации стандарта и поэтому просто уже не переписывали варнинги на ошибки из-за того, что уже так было принято. более чем нормальная ситуация.
Здравствуйте, ned, Вы писали:
ned>Добрый MS-компилятор, который только погрозит пальчиком на, например, такое: ned>
signed double float void bool int long b;
еще раз причины могли быть просто банальны: нужно было сохранить обратную совместимость. причин большое количество.
и это еще раз доказывает, что варнинги в MSVC более чем важны. просто для кучи оболтусов (хотя все программисты в той или иной степени такие), которые демонстрируют отношение что-то вроде: "программа работоспособна, если она откомпилировалась".
K>Смею разочаровать получи весь листинг твоего кода и окажется, что ты где-то написал #define bool int
Вы прежде чем нравоучения мутить, скомпилировали бы, а.
Указанный пример production кодом не является. Не беспокойтесь о нашем проекте, также можете попридержать нравоучения в стиле: "так писать плохо". Я и думаю все остальные вкурсе, что использовать этот "трик" нельзя, Капитан Очевидность. Прикол-то не в этом.
Здравствуйте, anonim_44ax, Вы писали:
_>Знает кто-нибудь нафига в С++ такие недо-типы? Это же еще хуже char, signed char, unsigned char. Если я верно понял, то signed и unsigned bool это typedef-ы соответственно:
Нет, это встроенные типы. Причем компилятор, который их понимает (любой C++ компилятор, и компилятор, понимающий C99) кладет туда только 0 и 1. Т.е. bool i = 5; положит в i единицу, а не 5.
Здравствуйте, anonim_44ax, Вы писали:
_>Специально для "танкистов" и klizardin уточняю.
_>Указанный пример production кодом не является. Не беспокойтесь о нашем проекте, также можете попридержать нравоучения в стиле: "так писать плохо". Я и думаю все остальные в курсе, что использовать этот "трик" нельзя, Капитан Очевидность. Прикол-то не в этом.
А в чем? В том, чтобы еще раз сказать бяки-буки мелкомягкие, они же не сделали эту ситуацию ошибкой, а сделали варнингом. Какие ужасные мелкомягкие! Это что-ли?
И даже не с точки зрения того, что "ведь все же мы делаем ошибки", а с точки зрения, что механизм предусмотрен сообщения об ошибке, а существование такого сообщения вполне может объясняться исторически. Или же что, мелкмягкие не вскрыли мозги всем программистам ради signed bool и не сделали ("как правильно") это ошибкой в некоторой новой версии? это что-ли?
В чем прикол?
это вообще не портируемая фича/баг и люди, которые вообще-то пишут хороший код, просто не будут использовать этот момент (потому что себе дороже да и не соответствует стандарту). или вы уверены, что все компиляторы написаны одной рукой и все они идентичны и только компилировались на разных языках и только из-за последнего и существуют и intel-овский компилятор и MSVC и тот же gcc. Каждый компилятор имеет свои особенности. Поэтому обычно для определения потенциальной портируемости библиотеки обычно есть тестовые куски кода, просто для проверки может ли язык(в данном случае C++) обрабатывать (и делать это корректно) определенные языковые конструкции. И естественно, есть свои нюансы у каждого из компиляторов.
***
Ну и если нужны морали)
Я не говорю, что так писать плохо. Плохо отключать варнинги и быть уверенным, что "ну это же только варнинги". И плохо поминать всуе мелкомягких (так как это же самое главное зло на планете) говоря, что ну вот они "реализовали" баг.
***
Вообще-то забавная фича, но фактически-то мне как программисту, что она дает? У MSVC были и куда веселее фичи.
_>Сломал мозг пока пытался себе представить "знаковое и беззнаковое ничто" _>Хотя вроде "правда с минусом" звучит более-менее логично (и значит пожалуй "неправда") {
Ха! А я вот подумал что правда с минусом, это всё-таки правда, но с очень плохими последствиями
Здравствуйте, TarasKo, Вы писали: _> return signed void(); TK>Ха! А я вот подумал что правда с минусом, это всё-таки правда, но с очень плохими последствиями
это все по просьбе Андриеску сделано, чтоб void функции удобней биндить
Здравствуйте, Masterkent, Вы писали:
M>По стандарту этот код вообще незаконен. Выражение int() — это преобразование типа в функциональной нотации, где нет вызова какого-либо конструктора (int — встроенный тип, и у него нет конструктора).
Ещё у Страуструпа, кажется, об этом есть, но нашёл не в нём, а в "Шаблонах С++" Вандевурда и Джосаттиса. Часто нужно делать вещи типа
T x = T();
и не думать, встроенный ли это тип.
По этой причине для встроенных типов можно явно вызывать стандартный конструктор, который инициализирует их нулём (или значением false для bool), т.е. int() даёт нуль.
Но здесь всегда требуется статья с пунктом... Вот нашёл, кажется (5.2.3/2):
The expression T(), where T is a simple-type-specifier (7.1.5.2) for a non-array complete object type or
the (possibly cv-qualified) void type, creates an rvalue of the specified type, whose value is determined by
default-initialization (8.5; no initialization is done for the void() case). [Note: if T is a non-class type
that is cv-qualified, the cv-qualifiers are ignored when determining the type of the resulting rvalue (3.10).]
По этой причине для встроенных типов можно явно вызывать стандартный конструктор, который инициализирует их нулём (или значением false для bool), т.е. int() даёт нуль.
Это выдумки, стандарт не связывает инициализацию скалярного объекта нулевым значением с вызовом какого-либо конструктора. Более того, даже если T — классовый тип, то в общем случае нельзя сказать, что выражение T() создаёт объект именно с помощью конструктора. В частности, конструктор по умолчанию никогда не вызывается для создания объектов POD-классов.
K>Но здесь всегда требуется статья с пунктом... Вот нашёл, кажется (5.2.3/2): K>
The expression T(), where T is a simple-type-specifier (7.1.5.2) for a non-array complete object type or
the (possibly cv-qualified) void type, creates an rvalue of the specified type, whose value is determined by
default-initialization (8.5; no initialization is done for the void() case). [Note: if T is a non-class type
that is cv-qualified, the cv-qualifiers are ignored when determining the type of the resulting rvalue (3.10).]
Я не вижу тут упоминания о конструкторе. И, кстати, это цитата из отменённого стандарта '98-го года. Действующим стандартом на данный момент является ISO/IEC 14882:2003(E) aka C++03.
По этой причине для встроенных типов можно явно вызывать стандартный конструктор, который инициализирует их нулём (или значением false для bool), т.е. int() даёт нуль.
M>Это выдумки, стандарт не связывает инициализацию скалярного объекта нулевым значением с вызовом какого-либо конструктора.
И кому из вас (непосредственно вам или книжке) верить?..
M> И, кстати, это цитата из отменённого стандарта '98-го года. Действующим стандартом на данный момент является ISO/IEC 14882:2003(E) aka C++03.
Разве что считать книгу устаревшей...
M> Более того, даже если T — классовый тип, то в общем случае нельзя сказать, что выражение T() создаёт объект именно с помощью конструктора. В частности, конструктор по умолчанию никогда не вызывается для создания объектов POD-классов. M> Я не вижу тут упоминания о конструкторе.
Да и не говорю ничего о конструкторе. Я хотел выяснить, почему void() и int() невалидны в качестве выражения.