Здравствуйте Poudy, Вы писали:
ПК>>В данном случае можно обойтись и без ковариантных возвращаемых значений: сделай operator << невиртуальным и пусть он вызывает соответствующие виртуальные методы при необходимости.
P>т.е. вы предлагаете сделать так?:
P>если так, то непонятно, зачем делать Put, Get виртуальными?
Если нет необходимости в виртуальности Put, Get как таковой, проблема отпадает сама собой :-)
P>И зачем вообще виртуальные функции... Собственно так я и делаю, только выглядит это странновато, поскольку приходится каждый раз заново описывать все операторы "туда-сюда".
Было бы лучше, если бы ты мог описать конкретные проблемы, возникающие при проектировании/кодировании конкретного класса. В данном случае, польза от ковариантных возвращаемых значений, да и от наследования классов Stream представляется сомнительной. Потоки в первую очередь предназначены как раз для предоставления унифицированного интерфейса для записи объектов. А если появляются их иерархии, серьезно между собой различающиеся, польза от общности протокола значительно падает.
P>А как в VC со ссылками на стандартные типы? У меня сейчас он не стоит.
В порядке.
P>В Borland не работают операции Stream >> i, если i, к примеру, int, поскольку вместо ссылки оператору передается копия.
Works for me, sample, please.
P>К сожалению, код потерян. Могу только под честное слово сказать, что никаких макросов и pragma не было (кроме полученных от stdio).
Тогда прими в той же степени обоснованный ответ, что подобных проблем у MSVC++ не наблюдается.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Уважаемый Павел Кузнецов.
ПК>Works for me, sample, please.
Кода уж очень много, поэтому кое-что все-таки поскипано.
Вот:
class clStream
{
protected:
unsigned int Offset;
public:
clStream(): Offset(0) {};
virtual unsigned int getSize() = 0;
int getOffset() { return Offset; }
void Back() { if(Offset > 0) Offset--; }
void Flush() { Offset = 0; }
bool isEndOf() { return (Offset < getSize()); }
};
template <class Unit>
class clIn: virtual public clStream
{
public:
clIn<Unit>& operator >> (Unit& unit) { unit = Get(); return *this; }
virtual Unit& Get ()= 0;
};
template <class Unit>
class clOut: virtual public clStream
{
public:
clOut<Unit>& operator << (Unit unit) { Put(unit); return *this; };
virtual void Put(Unit& unit)= 0;
};
template <class Unit>
class clInOut: virtual public clIn<Unit>,
virtual public clOut<Unit>
{
virtual Unit& Get ()= 0;
virtual void Put(Unit& unit)= 0;
};
template <class Unit>
class clArray: virtual public clInOut<Unit>
{
...
public:
...
Unit& operator[](int i);
// <Определения виртуальных функций, реализующих класс clInOut>
unsigned int getSize(void);
Unit& Get();
void Put(Unit& unit);
// </Определ...nOut>
};
Собственно Put & Get определялись не для ковариантных типов, а чтобы получать данные встроенных типов не через Array >> i, а через i = Array.Get();
Иначе происходит передача копии и i сохраняет свое значение.
Здравствуйте Poudy, Вы писали:
P>Посоветуйте компилятор, не только наиболее близкий к стандарту, но и без ошибок.
P>VC6 — не подходит. Не разрешает переопределение виртуальной функции, если меняется тип возвращаемого значения (со ссылки на базовый класс -> на ссылку на дочерний).
P>Borland 6.0 (среда, номера его компилера не помню) — тоже, т.к. плохо работает с шаблонами и странно наследует статические члены.
P>Может в Линух податься? Там есть хорошие среды разработки?
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте Poudy, Вы писали:
P>Здравствуйте Vsevolod V.Burkutsky, Вы писали:
VVB>>Попробуй Intel Compiler 6.0, он поближе.
P>Уже пробовал. Intel не подходит по той же причине, что и VC6. А пока у меня нет Itanium'а , от Intel нет большой выгоды, т.к. ускорение достигается почти только на "сплошных", без ветвлений, участках кода. Он циклы разворачивает, только жаль, что опция эта ставится для всего файла — в десять раз все циклы, например.
Странно... У меня как раз была именно эта проблема в VC6. Тогда я ее решил
использованием компилятора Intel (тогда еще 5й версии). VC7 также поддерживает
ковариантное возвращаемое значение.
Код был примерно такой:
class Record
{
public:
// ...virtual Record* Clone() const = 0;
// ...
};
class CashRecord : public Record
{
public:
// ...virtual CashRecord* Clone() const
{
return new CashRecord( *this );
};
// ...
};
Здравствуйте Poudy, Вы писали:
P>Здравствуйте Vsevolod V.Burkutsky, Вы писали:
VVB>>Попробуй Intel Compiler 6.0, он поближе.
P>Уже пробовал. Intel не подходит по той же причине, что и VC6. А пока у меня нет Itanium'а , от Intel нет большой выгоды, т.к. ускорение достигается почти только на "сплошных", без ветвлений, участках кода. Он циклы разворачивает, только жаль, что опция эта ставится для всего файла — в десять раз все циклы, например.
"To protect people you must slay people. To let people live you must let people die. This is the true teaching of the sword."
-Seijuro Hiko, "Rurouni Kensin"
Здравствуйте Poudy, Вы писали:
ПК>>Works for me, sample, please.
P>Кода уж очень много, поэтому кое-что все-таки поскипано.
<... code skipped ...>
P>Собственно Put & Get определялись не для ковариантных типов, а чтобы получать данные встроенных типов не через Array >> i, а через i = Array.Get(); P>Иначе происходит передача копии и i сохраняет свое значение.
Подозреваю, что что-то ты все-таки перепутал. Вот такая, аналогичная, программа:
#include <iostream>
class clStream { };
template <class Unit>
class clIn: virtual public clStream
{
public:
clIn<Unit>& operator >> (Unit& unit) { unit *= 10; return *this; }
};
template <class Unit>
class clOut: virtual public clStream
{
public:
clOut<Unit>& operator << (Unit unit) { return *this; };
};
template <class Unit>
class clInOut: virtual public clIn<Unit>,
virtual public clOut<Unit>
{
};
template <class Unit>
class clArray: virtual public clInOut<Unit>
{
};
int main()
{
clArray<int> array;
int i = 1, j = 2;
std::cout << i << ", " << j << std::endl;
array >> i >> j;
std::cout << i << ", " << j << std::endl;
return i + j;
}
как и ожидается, выдает:
1, 2
10, 20
Borland C++ 5.6 for Win32 Copyright (c) 1993, 2002 Borland
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте Павел Кузнецов, Вы писали:
ПК>Подозреваю, что что-то ты все-таки перепутал.
Я попробую еще раз, но могу заранее сказать, что загвоздка была только с виртуальными функциями, а так тот же Array со своим оператором [] работает как надо.
Есть еще одна проблема с Борландом — он не хочет делать встраиваемыми функции из шаблонов. Не знаю, есть ли на это новый стандарт, только вот он не только inline в шаблонах не переваривает (не линкует), но и описанные в ашнике невиртуальные функции вызывает по адресу, даже если они состоят всего из одной строчки.
Здравствуйте Павел Кузнецов, Вы писали:
ПК>>>В отношении соответствия стандарту и качества реализации работа хорошая, если не сказать больше — будь спок. В отношении среды, все просто: его можно встроить прямо в Visual Studio. В качестве back end он может использовать MSVC++, что, на мой взгляд, является еще одним плюсом, учитывая способности к оптимизации последнего.
ЮБ>>Заманчиво. А в среду от какой девстудии встраивается? Или в обе (6 и 7)?
ПК>Насчет встраивания: в MSVC++, как в 6, так и в 7 можно встроить любой компилятор. Достаточно сделать программу-драйвер, которая будет перекодировать входные опции, предназначенные для MSVC++ в опции для компилятора. В свое время я делал подобную программу для запуска из Visual Studio компиляторов bcc32 и gcc. Делали ли Comeau Computing подобную программу, я не знаю, думаю, что что-нибудь в этом духе где-нибудь должно быть. Главное же совместимость форматов для отладки. В этом отношении bcc32 и gcc не лучшие варианты. Т.к. Comeau в качестве back end использует MSVC++, это значительно улучшает ситуацию.
Это мысли вслух или реальный опыт использования? Если первое, то лично мне почему-то кажется, что с отладкой при использовании Comeau будут баальшие проблемы. Раз оно фронт-енд, то нагенерит малопонятный сишный код, для которого MSVC честно сделает дебаговскую информацию. Соответственно, при отладке получим доступ к этому промежуточному коду, а не к исходникам. Оно, конечно, лучше, чем ничего, но, IMHO, хуже, чем GDB aka Insight для gcc.
PS: Это только предположение, если кто-то юзал этот Камю, проясните ситуацию.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте Sergey, Вы писали:
S>Это мысли вслух или реальный опыт использования?
"Мой дядя видал, как барин едал" :-) В свое время довелось немного попользовать в целях тестирования, но без связи с MSVC++.
S>Если первое, то лично мне почему-то кажется, что с отладкой при использовании Comeau будут баальшие проблемы. Раз оно фронт-енд, то нагенерит малопонятный сишный код, для которого MSVC честно сделает дебаговскую информацию. Соответственно, при отладке получим доступ к этому промежуточному коду, а не к исходникам.
По этому поводу говорят, что он генерит промежуточный код с директивами #line, поэтому MSVC++ честно делает отладочную информацию со ссылками на оригинальный код :-).
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте Poudy, Вы писали:
P>Здравствуйте Vsevolod V.Burkutsky, Вы писали:
VVB>>Попробуй Intel Compiler 6.0, он поближе.
P>Уже пробовал. Intel не подходит по той же причине, что и VC6. А пока у меня нет Itanium'а , от Intel нет большой выгоды, т.к. ускорение достигается почти только на "сплошных", без ветвлений, участках кода. Он циклы разворачивает, только жаль, что опция эта ставится для всего файла — в десять раз все циклы, например.
Если эта причина:
"VC6 — не подходит. Не разрешает переопределение виртуальной функции, если меняется тип возвращаемого значения (со ссылки на базовый класс -> на ссылку на дочерний)."
То это не так, IC 6.0 компилит:
class A
{
protected:
int i;
public:
A():i(0){}
virtual A& Get(){ return *this; }
};
class B: public A
{
B(){ i = 1; }
virtual B& Get(){ return *this; }
};
Здравствуйте Poudy, Вы писали:
P>Посоветуйте компилятор, не только наиболее близкий к стандарту, но и без ошибок.
Если нужно обеспечить совместимость, то лучше всего gcc (www.mingw.org). Конечно, за нее придется платить понятно чем -- здесь уже писали об этом. Вполне работает такой вариант: отладочная версия пишется в gcc, а потом переносится на компилятор, заточеный под конкретную машину. Особых проблем на этом пути не возникает.
Тот, кто желает, но не делает, распространяет чуму.
Здравствуйте Raul, Вы писали:
R>Здравствуйте Poudy, Вы писали:
P>>VC6 — не подходит. Не разрешает переопределение виртуальной функции, если меняется тип возвращаемого значения (со ссылки на базовый класс -> на ссылку на дочерний).
R>Этот компилер действует в данном случае строго в соответсвии со стандартом С++. Да и вообще из тех каккие видел VC самый продвинутый и имеет самую лучшую среду разработчика. (Убью, кто не согласен).