Полнейший оффтоп: возьмите меня обратно :)

Profic

just Profic (PHP5 BetaTeam)
Полнейший оффтоп: возьмите меня обратно :)

В сабже упомянуто что это оффтоп полнейший и не имеющий никакого отношения к php, а к c++. Знаю, что есть другие форумы для этого, но этот как-то роднее :)

Писал я раньше на php и все было хорошо.
Так черт дернул - стал писать на c++ и столкнулся с совершенно непонятным багом: код
PHP:
l_left -= (a_props.m_marginLeft.isset() || a_props.m_marginRight.isset()
	? a_props.m_borderLeft.m_width
	: 0
);
вне зависимости от значений возвращаемых a_props.m_marginLeft.isset() и a_props.m_marginRight.isset() всегда вычетает 0.
Дебагил, дебагил, а толку - ноль. Плюнул и сделал такой код
PHP:
if (a_props.m_marginLeft.isset() || a_props.m_marginRight.isset()) {
	l_left -= a_props.m_borderLeft.m_width;
}
и, о чудо, все стало работать как положено.
Я почесал репу, посмотрел Страуструпа и впал в ступор: первый вариант должен работать также как и второй, но однако не работает. Что я делаю не так?

ЗЫ. После этого у меня появилось желание забить на c++... Возьмите меня обратно :)
ЗЫЫ. gcc version 3.4.2 (mingw-special)
 

SiMM

Новичок
PHP:
l_left -= (a_props.m_marginLeft.isset() || a_props.m_marginRight.isset() )
    ? a_props.m_borderLeft.m_width 
    : 0;
?
Может стоит перечитать главу о приоритетах операций для своего компилятора.
 

Profic

just Profic (PHP5 BetaTeam)
SiMM
по Cтрауструпу (а это по большому счету стандарт)
expr || expr
---
lvalue -= expr
---
expr ? expr : expr
т.е. в моем куске логическое или должно выполняться раньше всех, потом тернарный оператор, и в конце концов вычетание-присвоение

я вообще пробовал самый топорный вариант
PHP:
l_left -= ((a_props.m_marginLeft.isset() || a_props.m_marginRight.isset())
    ? a_props.m_borderLeft.m_width 
    : 0 
);
но и он не помог.
У меня закрались подозрения - а не баг ли это в компиляторе :)

-~{}~ 04.07.05 23:38:

Насколько я понимаю ассемблер x86 вот это интересующий меня кусок:
Код:
0x004431c1: call   0x4a502c <_ZNK9RtfParser8PropertyIdLb0ELb0EE5issetEv>
0x004431c6: test   al,al
0x004431c8: jne    0x4431e0 <_ZN9RtfParser8Rtf2Html10tableStyleERKNS_8PropsRowE+338>
0x004431ca: mov    eax,DWORD PTR [ebp+16]
0x004431cd: add    eax,0x1e8
0x004431d2: mov    DWORD PTR [esp],eax
0x004431d5: call   0x4a502c <_ZNK9RtfParser8PropertyIdLb0ELb0EE5issetEv>
0x004431da: test   al,al
0x004431dc: jne    0x4431e0 <_ZN9RtfParser8Rtf2Html10tableStyleERKNS_8PropsRowE+338>
0x004431de: jmp    0x44323f <_ZN9RtfParser8Rtf2Html10tableStyleERKNS_8PropsRowE+433>
0x004431e0: mov    eax,DWORD PTR [ebp+16]
0x004431e3: add    eax,0x2f8
0x004431e8: mov    DWORD PTR [esp],eax
0x004431eb: mov    DWORD PTR [ebp-360],0x2d
0x004431f5: call   0x4a5068 <_ZNK9RtfParser8PropertyIdLb1ELb0EEcvdEv>
0x004431fa: fnstcw WORD PTR [ebp-366]
0x00443200: movzx  eax,WORD PTR [ebp-366]
0x00443207: or     ax,0xc00
0x0044320b: mov    WORD PTR [ebp-368],ax
0x00443212: fldcw  WORD PTR [ebp-368]
0x00443218: fistp  DWORD PTR [ebp-372]
0x0044321e: fldcw  WORD PTR [ebp-366]
0x00443224: mov    eax,DWORD PTR [ebp-372]
0x0044322a: push   eax
0x0044322b: fild   DWORD PTR [esp]
0x0044322e: lea    esp,[esp+4]
0x00443232: fld    QWORD PTR [ebp-32]
0x00443235: fsubp  st(1),%st
0x00443237: fstp   QWORD PTR [ebp-392]
0x0044323d: jmp    0x443248 <_ZN9RtfParser8Rtf2Html10tableStyleERKNS_8PropsRowE+442>
0x0044323f: fld    QWORD PTR [ebp-32]
0x00443242: fstp   QWORD PTR [ebp-392]
0x00443248: fld    QWORD PTR [ebp-392]
0x0044324e: fstp   QWORD PTR [ebp-32]
0x00443251: lea    eax,[ebp-32]
0x00443254: mov    DWORD PTR [esp+4],eax
0x00443258: mov    eax,DWORD PTR [ebp+16]
0x0044325b: add    eax,0x18
но я его ничерта не понимаю :(
 

ironic

Guest
да... С\C++ это 4ever!

Но как-то не вижу причин програмить на ем, только под железяку какую :) тотогда только на сях...

Чччерт, ностльгия у меня однако по программированию контроллеров...
 

.des.

Поставил пиво кому надо ;-)
Profic тестовый пример.
Код:
#include <iostream>
struct margin { bool isset() { return true; } };
struct border { int width; };
struct prop {
	margin mleft, mright;
	border bleft;
};
int main() {
	int left = 10;
	prop a;
	a.bleft.width = 5;
	left -= a.mleft.isset() || a.mright.isset() ?  a.bleft.width : 0; 
	std::cout << left << std::endl;
	return 0;
}
что печатает?
 

Profic

just Profic (PHP5 BetaTeam)
.des.
5, как и должен

Упс, совсем забыл сказать:
все переменные типа double
объект a_props.m_borderLeft (как и margin*) является экземпляром класса с объявленным operator float()

Тестовый пример переделанный с учетом этого так же выдает 5.
 

AnToXa

prodigy-одаренный ребенок
мама дорогая, понапишут всякого, а потом удивляйся.

0.0 напиши там внутри тернарного оператора и почитай http://www.artima.com/cppsource/foreach.html

-~{}~ 05.07.05 14:33:

неявные преобразования - опасная штука, аха.
 

Profic

just Profic (PHP5 BetaTeam)
AnToXa
Явно born programmer! Я подумал об типах, но потом решил, что это не про то, забил и стал париться с приоритетами... Оказывается про то.

Мдя я думал, что int сконвертиться во float т.к. второй операнд тернарного оператора есть "double"... А оказалось все немного сложнее...

Еще раз, чтобы окончательно понять:
весь тернарный оператор в случае с '0' получает тип int из-за того, что мой объект конвертится в double, который конвертится в int. В то время как int в мой класс не может. Я правильно понял?

Added1:
Только что убедился (по моим представлениям) в верности своих догадок. Код
PHP:
l_left -= (a_props.m_marginLeft.isset() || a_props.m_marginRight.isset()
	? a_props.m_borderLeft.m_width.get()
	: 0
);
работает как положено. get() как раз возвращает double :)

Added2:
Неявные пребразования опасная штука, аха :)
 

AnToXa

prodigy-одаренный ребенок
Profic

перечитал еще раз стандарт вот, для тебя важен п. 5.16/3.

Еще раз, чтобы окончательно понять:
весь тернарный оператор в случае с '0' получает тип int из-за того, что мой объект конвертится в double, который конвертится в int. В то время как int в мой класс не может. Я правильно понял?
да, у тебя первая ветка имеет class type, а вторая - rvalue с типом int, соответственно ищется преобразование в int, которое находится через float, причем есть правило, что в цепочке неявного преобразования типов не может быть больше одной user-defined conversion, но тут все нормально.

собсна это само по себе могло только поломать точность, но не зставить все время возвращать 0, разве что у тебя там значения меньше 1 :)

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

-~{}~ 05.07.05 19:09:

кстати, венгерская нотация сосет :)
 

Profic

just Profic (PHP5 BetaTeam)
AnToXa
собсна это само по себе могло только поломать точность, но не зставить все время возвращать 0, разве что у тебя там значения меньше 1 :)
именно, толшина рамки в rtf-е, на котором я такое заметил - 0.5 пункта. Переделанный на предмет моих условий пример .des.-а дает 1, а не 0.5
PHP:
#include <iostream>
struct property {
	float value;
	operator double() { return value; }
	bool isset() { return true; }
};
struct border { property width; };
struct table {
	property mleft, mright;
	border bleft;
};
int main() {
	double left = 1;
	table a;
	a.bleft.width.value = 0.5;
	left -= a.mleft.isset() || a.mright.isset() ?  a.bleft.width : 0;
	std::cout << left << std::endl;
	return 0;
}
кстати, венгерская нотация сосет :)
на вкус и цвет... :)
 
Сверху