Но в результате я так и не понял — что это, в чем там фича?
Понятно что некоторые типы могут порождать объекты динамического размера. В С++ хотя-бы std::vector и std::list. Но это и так понятно и придумано уже давно.
А здесь что?
Re: Что такое Dynamically-sized types (DSTs) в Rust ?
Здравствуйте, x-code, Вы писали:
XC>Понятно что некоторые типы могут порождать объекты динамического размера. В С++ хотя-бы std::vector и std::list. Но это и так понятно и придумано уже давно.
XC>А здесь что?
std::vector и std::list — структуры постоянного размера (и известного при компиляции), содержащие указатели на память в куче.
Вот получаешь ты в функцию адрес чего-то. И хочешь это что-то скопировать по значению. Для этого надо знать как минимум, сколько байт копировать. Если это примитивный тип или тупл/структура, то размер компилятору известен статически, все ок. std::vector и std::list как раз такие.
А вот если это что-то описано как объект некоторого класса, и этот класс служит базовым для некоторых других, то возможно, что вместо объекта базового класса там окажется объект наследного, он может быть уже другого размера. Что там на самом деле — известно лишь в рантайме, вот и получается тип динамического размера. Если копировать, полагаясь на известный при компиляции тип, то объект может быть скопирован не целиком, получается слайсинг, беда. Поэтому в цивизизованных ОО языках все объекты размерщают в куче и передают лишь по указателю, по значению их не копируют.
Аналогично и тут, только вместо базового класса trait, который служит аналогом интерфейса. Если известен лишь интерфейс/trait, то размер объекта, который его реализует, неизвестен статически, он динамический.
Re[2]: Что такое Dynamically-sized types (DSTs) в Rust ?
Здравствуйте, D. Mon, Вы писали:
DM>А вот если это что-то описано как объект некоторого класса, и этот класс служит базовым для некоторых других, то возможно, что вместо объекта базового класса там окажется объект наследного, он может быть уже другого размера. Что там на самом деле — известно лишь в рантайме, вот и получается тип динамического размера. Если копировать, полагаясь на известный при компиляции тип, то объект может быть скопирован не целиком, получается слайсинг, беда. Поэтому в цивизизованных ОО языках все объекты размерщают в куче и передают лишь по указателю, по значению их не копируют. DM>Аналогично и тут, только вместо базового класса trait, который служит аналогом интерфейса. Если известен лишь интерфейс/trait, то размер объекта, который его реализует, неизвестен статически, он динамический.
ОК, то есть если тип динамический (точно известен лишь в рантайме — в частности указатель на базовый класс) то и размер динамический — это понятно. Ну а фича-то в чем? Как в С++ жили без этого и почему в Rust это вдруг понадобилось?
Кстати, еще вспоминается низкоуровневая фича из Си "struct hack" — там тоже размер фактического объекта динамический и известен лишь в рантайме:
struct FOO {
int size;
char buf[0]; // buf[size]
};
хотел упомянуть в первом сообщении, но непонятно в тему ли это...
Здравствуйте, x-code, Вы писали:
XC>ОК, то есть если тип динамический (точно известен лишь в рантайме — в частности указатель на базовый класс) то и размер динамический — это понятно. Ну а фича-то в чем? Как в С++ жили без этого и почему в Rust это вдруг понадобилось?
В C++, нецивилизованном языке, жили как привыкли — компилятор ничего не обещает, все потенциальные косяки на совести программиста, пусть берет дебаггер и ищет ошибку сам. В Rust же взялись обеспечить какие-то гарантии.
XC>Кстати, еще вспоминается низкоуровневая фича из Си "struct hack" — там тоже размер фактического объекта динамический и известен лишь в рантайме:
Rust такое теперь тоже позволяет, вроде.
Re[4]: Что такое Dynamically-sized types (DSTs) в Rust ?
Здравствуйте, D. Mon, Вы писали:
DM>В C++, нецивилизованном языке, жили как привыкли — компилятор ничего не обещает, все потенциальные косяки на совести программиста, пусть берет дебаггер и ищет ошибку сам. В Rust же взялись обеспечить какие-то гарантии.
Я туплю наверное, но все-же в чем фича? Что именно они сделали и как теперь это работает?
Пока я понял только приблизительную область, к которой относится проблема и решение...
Re[5]: Что такое Dynamically-sized types (DSTs) в Rust ?
Здравствуйте, x-code, Вы писали:
XC> Что именно они сделали и как теперь это работает?
Я сам пока не знаю подробностей. Судя по всему, сделали для таких типов толстые указатели (содержащие второе слово — размер) и вписали в остальную систему типов, чтобы это было более-менее прозрачно.
Re[3]: Что такое Dynamically-sized types (DSTs) в Rust ?
Здравствуйте, x-code, Вы писали:
XC>ОК, то есть если тип динамический (точно известен лишь в рантайме — в частности указатель на базовый класс) то и размер динамический — это понятно. Ну а фича-то в чем? Как в С++ жили без этого и почему в Rust это вдруг понадобилось?
ну это и в сях может понадобиться:
struct test {
virtual ~test () {}
virtual void foo () = 0;
};
struct test1 : test {
virtual void foo () {}
};
struct test2 : test {
virtual void foo () {}
};
struct test_factory {
virtual int capacity ( ) = 0;
virtual test * create ( char * buffer ) = 0;
};
template< typename Test >
struct test_factory_impl : test_factory {
virtual int capacity ( ) { return sizeof( Test ) + 4; }
virtual test * create ( char * buffer ) { return new(buffer) Test(); }
};
test_factory * foo ( ) {
if ( rand() % 2 ) {
static test_factory_impl< test1 > f1;
return &f1;
} else {
static test_factory_impl< test2 > f2;
return &f2;
}
}
int main () {
for ( int i = 0; i < 2; ++i ) {
test_factory * f = foo ( );
local_ptr<test> t = f->create( alloca( f->size( ) ) );
t->foo( );
}
}
не знаю, как проще написать. здесь присутствуют очевидные ограничения.
если в Rust что-то сделали что-то такое, то это неплохо.
Вообще, раз уж на то пошло и вся фишка тут в копировании, чтобы копировать объект динамического размера в С++ используется такой интерфейсик:
struct ICloneable
{
ICloneable* Clone() = 0;
}
class A : ICloneable
{...};
Дальше думаю понятно. Имея указатель на базовый класс всегда можно сделать полную копию его истинного рантайм класса.
Конечно тут потребуется немного макросомагии, чтобы вставлять обязательный boilerplate код в каждый из классов наследников.
Здравствуйте, johny5, Вы писали:
J>Вообще, раз уж на то пошло и вся фишка тут в копировании, чтобы копировать объект динамического размера в С++ используется такой интерфейсик:
J>
J>struct ICloneable
J>
J>Дальше думаю понятно. Имея указатель на базовый класс всегда можно сделать полную копию его истинного рантайм класса. J>Конечно тут потребуется немного макросомагии, чтобы вставлять обязательный boilerplate код в каждый из классов наследников.
не, это чуть из другой оперы.
тот пример, что я привел, позволяет создавать динамические объекты например в стеке.