Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Все, извини, но это письмо будет точно последним. Времени больше на эти дискуссии нет — увы, заказчик прислал наконец спецификации проекта, и он именно на С# .
Заказчик всегда прав!
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, VladD2, Вы писали:
IT>>Индусы что-ли?
VD>У тебя уже на них фобия.
У меня на них миллиард фобий. Или сколько их там.
VD>Нет конечно. Но не нужно быть индусом чтобы на плюсах создать проект который будет компилироваться пол часа на одной машине.
Они не на Watcom случайно проект делают, который состоит из одних шаблонов? Тогда в лёгкую. А так надо очень постараться.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, VladD2, Вы писали:
VD>Это старый АПИ. Оно не будет работать на машинах с новым вордом. По крайней мере на моей машине где стоит Word 2003 оно не работает.
Влад может на счет АПИ ты и прав, но у меня Word 2003 SP2 и оно работает.
Здравствуйте, Alexey Axyonov, Вы писали:
VD>>Это старый АПИ. Оно не будет работать на машинах с новым вордом. По крайней мере на моей машине где стоит Word 2003 оно не работает.
AA>Влад может на счет АПИ ты и прав, но у меня Word 2003 SP2 и оно работает.
В SP2 похоже многие глюки пофиксили. Может услышали как я разоряюсь?
Но SP2 появился только сейчас. А Ворду уже много лет и как минимум 10 из них он содержал в себе один и те же глюки.
Кстати, точно сказать, что глюки пофиксили пока не могу, так как времени прошло немного с выхода SP2. Но через месяцок другой скажу.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, FR, Вы писали:
GN>>Думаю для определённых (узких) классов задач решения будут постепенно возникать. Я бы и сам с радостью купил писюк, который весь (кроме монитора) находится в клавиатуре .
FR>Давно забытое старое? (синклер, микроша, вектор, поиск) FR>Да и сейчас есть тот же mac-mini
Мне вот нравятся маленькие такие ноуты, с книжку размером, с dvd-rw приводом, экранчиком 10".
Однако стоят такие хреновинки 50-60т.р. ($1600-2000).
Вот за 300 баксов бы я такой себе хоть щщас взял
Что интересно, стандартные большие ноуты стоят в 2-3 раза дешевле маленьких.
Когда цены на миниатюрные решения станут адекватными для простых граждан?
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Компилятор с Фортрана на 96 КБайтах работал, c PL/1 — даже на 64 Кбайтах (до сих PD>пор не знаю, почему — PL/1 сложнее Фортрана), линкеру тоже 96 Кбайт хватало,
Они были жутко оверлейные... Чем им было доступно больше памяти, тем они быстрее работали. Оптимизирующему компилялятору PL/1 памяти было нужно заметно больше, чем стандартному.
S>Совершенно верно! Но, к сожалению, это была бы совсем другая программа. S>И Павел не будет ее писать. Потому, что strlen — это медленная операция, а он-то как раз хотел сэкономить лишний проход по данным.
а кто мешает юзать snprintf()? Как раз для таких случаев предназначена, свои проверки можно не делать.
Здравствуйте, GlebZ, Вы писали:
>>> А string вообще кошмар, но зато жутко удобный. ПК>>Это к уровню языка отношения не имеет. GZ>В честь чего. В С++ два основных типа строк.(пишу именно основных, чтоб не наезжали) Строка и нестрока, то есть string и char[]. string объект ООП — char[] наследие С. Кто из них высокоуровневая конструкция, а кто тормозная?
быстродействие выделения/удаления std::string напрямую зависит от алокатора. Все остальные операции сравнимы по эффективности... Некоторые алгоритмы могут работать гораздо быстрее за счет агрессивного инлайнинга.
Напиши аллокатор статического типа (или попроси меня прислать исходник), и ты получишь ООП-строку, не уступающую char[].
Здравствуйте, vdimas, Вы писали:
V>быстродействие выделения/удаления std::string напрямую зависит от алокатора. Все остальные операции сравнимы по эффективности... Некоторые алгоритмы могут работать гораздо быстрее за счет агрессивного инлайнинга.
V>Напиши аллокатор статического типа (или попроси меня прислать исходник), и ты получишь ООП-строку, не уступающую char[].
Ну уступающего char[] в стеке?
Здравствуйте, GlebZ, Вы писали:
GZ>Здравствуйте, vdimas, Вы писали:
V>>быстродействие выделения/удаления std::string напрямую зависит от алокатора. Все остальные операции сравнимы по эффективности... Некоторые алгоритмы могут работать гораздо быстрее за счет агрессивного инлайнинга.
V>>Напиши аллокатор статического типа (или попроси меня прислать исходник), и ты получишь ООП-строку, не уступающую char[]. GZ>Ну уступающего char[] в стеке?
Здравствуйте, vdimas, Вы писали:
V>>>Напиши аллокатор статического типа (или попроси меня прислать исходник), и ты получишь ООП-строку, не уступающую char[]. GZ>>Ну уступающего char[] в стеке?
V>именно
Гонишь. Давай поясню что такое char[]. В отличие от string — это не массив, а всего лишь набор объектов. И даже копирование строк можно делать несколькими способами — перекопируя память через memmove, strcpy, или вручную построенным циклом. То есть способов не нарушающих инкапсуляцию char[] до фигищи. И кое какие из них — менее эффективны а какие-то более эффективны. К тому же strcpy можно легко проинлайнить, и я сомневаюсь что кто-то его обгонит, даже теоретически.
Здравствуйте, GlebZ, Вы писали:
GZ>Здравствуйте, vdimas, Вы писали:
V>>>>Напиши аллокатор статического типа (или попроси меня прислать исходник), и ты получишь ООП-строку, не уступающую char[]. GZ>>>Ну уступающего char[] в стеке?
V>>именно GZ>Гонишь. Давай поясню что такое char[]. В отличие от string — это не массив, а всего лишь набор объектов. И даже копирование строк можно делать несколькими способами — перекопируя память через memmove, strcpy, или вручную построенным циклом. То есть способов не нарушающих инкапсуляцию char[] до фигищи. И кое какие из них — менее эффективны а какие-то более эффективны. К тому же strcpy можно легко проинлайнить, и я сомневаюсь что кто-то его обгонит, даже теоретически.
а разве ты только копируешь строки??? мне казалось, что ты их еще сравниваешь и в коллекции ложишь и т.д.
В общем, могу дать стековый аллокатор и не смущай народ
GlebZ wrote: > V>именно > Гонишь.
Пример из моей BTL (Bicycle Template Library ) — политика хранения,
использующая небольшой стековый буфер для оптимизации:
///////////////////////////////////////////////////////////////////////////////////////
////// Small-Storage-Optimization
///////////////////////////////////////////////////////////////////////////////////////namespace aux
{
//This union is used to ensure that SSO storage elements will be
properly aligned.
template<size_t small_storage_size, class StorageT> union sso_storage_data
{
typedef typename StorageT::value_type value_type;
typename boost::type_with_alignment<
(boost::alignment_of<StorageT>::value >
boost::alignment_of<value_type>::value)
? boost::alignment_of<StorageT>::value
: boost::alignment_of<value_type>::value
>::type a;
char storage_[sizeof(StorageT)];
char data_[small_storage_size*sizeof(value_type)];
};
struct dummy_type { int dummy_; };
};
template<size_t small_storage_size,class StorageT> class sso_storage :
private boost::noncopyable,
//Use EBO for allocator. Note: workaround for VC bug!private StorageT::allocator_type::template rebind<aux::dummy_type>::other
{
//There is no sense in zero-sized sso!
BOOST_STATIC_ASSERT(small_storage_size!=0);
typedef typename StorageT::allocator_type::template rebind<
aux::dummy_type>::other rebound_alloc;
//Type of this class, useful for generic codetypedef sso_storage<small_storage_size,StorageT> this_class;
//Type of the small storagetypedef aux::sso_storage_data<small_storage_size,StorageT> data_type;
//Magic size indicates we've reverted to the main storage.static const size_t magic_size=small_storage_size+1;
//small_storage_size is insanely large - magic_size overflows!
BOOST_STATIC_ASSERT((magic_size>small_storage_size));
//SSO might be used only for POD-like types due to exception-safety
issues. TODO: add support for nothrowing copyctors.
BOOST_MPL_ASSERT((bitwise_moveable<typename StorageT::value_type>));
public://protected:typedef StorageT delegate_storage;
typedef typename StorageT::move_traits move_traits;
typedef typename StorageT::value_type value_type;
typedef typename StorageT::size_type size_type;
typedef typename StorageT::allocator_type allocator_type;
typedef sso_const_iterator<this_class> const_iterator;
typedef sso_iterator<this_class> iterator;
//Storage constructionexplicit sso_storage(const allocator_type &_alloc=allocator_type()) :
rebound_alloc(_alloc), size_()
{
}
//Destructor:
~sso_storage()
{
reset();
}
//Data accessor methods:
value_type* begin_ptr()
{
if (size_==magic_size)
return get_storage().begin_ptr();
return reinterpret_cast<value_type*>(buffer_.data_);
}
const value_type* begin_ptr() const
{
return const_cast<this_class*>(this)->begin_ptr();
}
iterator begin()
{
if (size_==magic_size)
return iterator(get_storage().begin());
else
return iterator(begin_ptr(),true);
}
const_iterator begin() const
{
//Note we have to remove constantness from the delegate iterator.if (size_==magic_size)
return const_iterator((const_cast<StorageT&>(get_storage())).begin());
else
return const_iterator(begin_ptr(),true);
}
value_type* end_ptr()
{
if (size_==magic_size)
return get_storage().end_ptr();
return reinterpret_cast<value_type*>(buffer_.data_)+size_;
}
const value_type* end_ptr() const
{
return const_cast<this_class*>(this)->end_ptr();
}
iterator end()
{
if (size_==magic_size)
return iterator(get_storage().end());
else
return iterator(end_ptr(),true);
}
const_iterator end() const
{
//Note we have to remove constantness from the delegate iterator.if (size_==magic_size)
return const_iterator((const_cast<StorageT&>(get_storage())).end());
else
return const_iterator(end_ptr(),true);
}
//Size/capacity:
size_type size() const
{
if (size_==magic_size)
return get_storage().size();
return size_;
}
size_type max_size() const
{
size_type sz;
if (size_==magic_size)
sz=get_storage().max_size();
else
sz=StorageT(*this).max_size();
assert(sz>small_storage_size); //Sanity checkreturn sz;
}
size_type capacity() const
{
if (size_==magic_size)
return get_storage().capacity();
return small_storage_size;
}
bool empty() const
{
return size()==0;
}
void set_size(size_type _new_size)
{
assert(_new_size<=capacity());
if (size_==magic_size)
get_storage().set_size(_new_size);
else
size_=_new_size;
}
allocator_type get_allocator_inst() const
{
return allocator_type(*this);
//const_cast<allocator_type&>(allocator_type(*this));
}
void reserve(size_type _new_size)
{
if (_new_size<=capacity())
return;
if (_new_size>max_size())
throw ::std::length_error("This storage can't handle such allocations");
if (size_==magic_size) //SSO is inactive
get_storage().reserve(_new_size);
else
{
//SSO is active, need to disable it.
allocator_type alloc(get_allocator_inst());
StorageT tmp(alloc);
tmp.reserve(_new_size);
move_traits::move(begin_ptr(),end_ptr(),tmp.begin_ptr(),alloc);
tmp.set_size(size());
reset();
create_storage();
get_storage().move_from(tmp);
}
}
void copy_from(const this_class &_other)
{
reset();
if (_other.size_==magic_size) //Check if SSO is inactive.
{
create_storage();
get_storage().copy_from(_other.get_storage());
}
else
{
assert(_other.size()<=small_storage_size); //Data should fit into
small buffer.
allocator_type alloc(get_allocator_inst());
//No need to call reserve, because we can't hit reallocation.
move_traits::copy(_other.begin_ptr(),_other.end_ptr(),begin_ptr(),alloc);
set_size(_other.size());
}
}
void move_from(this_class &_other)
{
reset();
if (_other.size_==magic_size) //Check if SSO is inactive.
{
create_storage();
get_storage().move_from(_other.get_storage());
_other.reset();
}
else
{
assert(_other.size()<=small_storage_size); //Data should fit into
small buffer.
allocator_type alloc(get_allocator_inst());
//No need to call reserve, because we can't hit reallocation.
move_traits::move(_other.begin_ptr(),_other.end_ptr(),
begin_ptr(),alloc); //May NOT throw.
set_size(_other.size());
_other.reset();
}
}
bool vacuum()
{
if (size_==magic_size)
return get_storage().vacuum();
return false; //We can't vacuum static storage.
}
void mutating()
{
if (size_==magic_size)
get_storage().mutating();
}
void swap(this_class & _other)
{
//Check if SSO is inactive - in this case just delegate swap to the
underlaying storages.
if (size_==magic_size && _other.size_==magic_size)
get_storage().swap(_other.get_storage());
else
{
//SSO is active at least on one storage, have to use slower swap.if (size_==magic_size || empty()) //SSO is active on the other storage.
{
//Move our data to the temporary storage (if it's present).
StorageT tmp(get_allocator_inst());
if (!empty())
tmp.move_from(get_storage());
reset();
//Move data from _other to our small buffer
move_from(_other);
_other.create_storage();
_other.get_storage().move_from(tmp);
} else
_other.swap(*this); //This will hit previous branch on recursion.
}
}
void reset()
{
if (size_==magic_size)
destroy_storage();
else
{
for(value_type* f=begin_ptr();f!=end_ptr();f++)
f->~value_type();
size_=0;
}
}
public: //Make custom methods accessible to client.bool sso_active() const
{
return size_!=magic_size;
}
StorageT& get_underlying_storage()
{
assert(!sso_active());
return get_storage();
}
private:
void create_storage()
{
assert(size_==0); //Storage must be clean
allocator_type alloc(get_allocator_inst());
new(buffer_.storage_) StorageT(alloc);
size_=magic_size;
}
void destroy_storage()
{
get_storage().~StorageT();
size_=0;
}
StorageT& get_storage()
{
assert(size_==magic_size);
return reinterpret_cast<StorageT&>(buffer_.storage_);
}
const StorageT& get_storage() const
{
assert(size_==magic_size);
return reinterpret_cast<const StorageT&>(buffer_.storage_);
}
data_type buffer_;
size_type size_;
};
Поддерживается автоматическое переключение на другую политику хранения,
если размер буффера оказывается недостаточным. В следующей версии еще
добавится более эффективная поддержка для контейнеров, где не нужен
непрерывный блок памяти.
Размер статического хранилища задается параметром темплейта. При желании
можно использовать alloca и задавать размер динамически.
Здравствуйте, Cyberax, Вы писали:
C>McSeem2 wrote:
C>Кстати, у нас в постановке проекта так и звучало: "Переделать прототип C>приложения c C# на С++" Между строчками читалось: "Эта <пиииииии> C>программа на C# не может делать ни <пииииииииии>. Сделайте нам нормальную."
Может это, того, проектную команду надо было поменять, а не язык? Потому как 99% ПО можно писать на чем угодно — разница т-ко в скорости разработки.