Здравствуйте, sci_reseacher, Вы писали:
_>в одном классе мне нужен std::vector<T>, в другом T*, т.к. это две разные реализации класса, работающие на разных устройствах --- а пользователь их может выбирать.
А что мешает доставать float* из вектора просто?
Зачем хранить две идентичные копии данных?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, sci_reseacher, Вы писали:
_>>в одном классе мне нужен std::vector<T>, в другом T*, т.к. это две разные реализации класса, работающие на разных устройствах --- а пользователь их может выбирать.
E>А что мешает доставать float* из вектора просто? E>Зачем хранить две идентичные копии данных?
Технологии, используемые в классе с полем T* не могут работать с vector<T> и предоставляют для чтения из некоторой области памяти T* ...
Появилась необходимость в классе B, который использует совсем другие технологии расчета и хранения данных (с std::vector не работает),
но предоставляет указатель float * для обращения к непрерывному участку памяти. Хотелось бы не меняя интерфейс и логику
всех модулей и программ в классе B сделать setX такой же как и в классе A
struct B: public Base {
float* X;
int size;
B(){ /* .. */ }
void work() { /* hard calc. for X */ }
const std::vector<float> & setX() { return/* ..*/; }
};
Похоже, что единственный вариант, сделать в B() поле std::vector или в Base его перенести.
E>Здравствуйте, sci_reseacher, Вы писали:
_ E>1) А зачем tmp не временный? Можно же так: E>
struct A
E>{
E> float* X_;
E> int size;
E> vector<float> getX(){
E> return vector<float> tmp(X_,X_+size);
E> }
_>>};
E>
E>2) Зачем возвращать ссылку? Можно же просто копию, в надежде на RVO, а если объект временным делать нельзя, то NRVO E>3) Если С++11 и позже, то возвращаемое значение можно через мув-конструктор получать, что недорого E>4) Главное, зачем вообще этот массив float'ов копировать в вектор? Можно же просто возвращать два указателя, в качестве итераторов?
_>Появилась необходимость в классе B, который использует совсем другие технологии расчета и хранения данных (с std::vector не работает), _>но предоставляет указатель float * для обращения к непрерывному участку памяти. Хотелось бы не меняя интерфейс и логику
Здравствуйте, sci_reseacher, Вы писали:
_>Технологии, используемые в классе с полем T* не могут работать с vector<T> и предоставляют для чтения из некоторой области памяти T* ...
То есть данными владеют "технологии"? Или ты им буфер предоставляешь?
18.05.16 12:10: Удалено модератором из 'C/C++'.
18.05.16 12:10: Восстановлено модератором.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, sci_reseacher, Вы писали: _>нужно сделать наследников D и C класса B, таких, что в одном данные хранятся в std::vector<T>, а в другом классе T* указывает на эти данные.
Скрытый текст
_>
_>struct B {
_> virtual const vector<float> & getX() = 0 ;
_>};
_>struct C: public B {
_> float *X;
_> int size;
_>// vector<float> getX(){
_>// vector<float> tmp(X,X+size);
_>// return tmp;
_>// }
_>};
_>struct D: public B {
_> vector<float> X;
_> const vector<float> & getX(){
_> return X;
_> }
_>};
_>
_>наверное лучший вариант переделать базовый класс _>
_>struct C: public B {
_> float *X;
_> int size;
_> virtual vector<float> getX(){
_> vector<float> tmp(X,X+size);
_> return tmp;
_> }
_>};
_>struct D: public B {
_> vector<float> X;
_> virtual vector<float> getX(){
_> return X;
_> }
_>};
_>
_>и использовать так _>
_>const vector<float> & w = d.getX(); // только вот здесь для D d нет ли лишней копии вектора? всегда работает return value optimization?
_>
Я сомневаюсь, что это лучший вариант, т.к. это потеря и в скорости, и в расходе памяти.
Смотрите: вам нужно к объектам разной природы предоставить единый интерфейс.
Возвращать vector — значит конвертировать один тип (T*) в другой — std::vector<T>. Это самый тривиальный способ, но есть и другие подходы.
Например, выделить у T* и std::vector<T> общий интерфейс и дать к нему доступ.
Общим специфичным интерфейсом для T* и std::vector<T> является индексный доступ, поэтому можно в базовом классе вместо
Это незначительный проигрыш в скорости, но без потерь в памяти. Если в этой иерархии у вас не планируется третий класс, элементы которого будут хранится в контейнере не допускающим индексный доступ, то на этом можно остановится.
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, sci_reseacher, Вы писали:
_>>Появилась необходимость в классе B, который использует совсем другие технологии расчета и хранения данных (с std::vector не работает), _>>но предоставляет указатель float * для обращения к непрерывному участку памяти. Хотелось бы не меняя интерфейс и логику
J>Переделай интерфейс на array_view.
имеется ввиду вот эта обертка ? или есть еще какой-то wrapper?
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, sci_reseacher, Вы писали:
_>>имеется ввиду вот эта обертка ? или есть еще какой-то wrapper?
J>Да, эта вполне подойдет. А в следующем стандарте или через один будет встроенный std::array_view
если уж переделывать интерфейс базового класса, то а вот я не пойму: чем же будет лучше возвращать array_view<T>, а не T*?
float* getX(){ };
P.S. извиняюсь, не знаю как удалить сообщение, все, понял ... интерфейс вектора там повторяется и модули работающие с редактируемым классом не нужно править
вот здесь теперь можно быть уверенным, что всегда по ссылке ссылкам ref_a, ref_b ... будет доступен актуальный внутренний "array" на чтение без лишних "телодвижений" (копирования приводящего к расходу памяти и времени)?
struct A {
std::vector<float> X;
A(){ X.resize(10,5);}
void work(void) { std::fill(X.begin(),X.end(),6); }
arv::array_view<float> getX(){
return X;
}
};
struct B {
float* X;
B(){ X = new float[10];}
void work(void) { for(int i=0; i<10; ++i) X[i] = i; }
arv::array_view<float> getX(){
return {&X[0],10};
}
};
struct C {
std::valarray<float> X;
C(){ X.resize(5);}
void work(void) { X += 3.14; }
arv::array_view<float> getX(){
return {&X[0],X.size()};
}
};
A a;
const arv::array_view<float> & ref_a = a.getX();
B * b = new B;
const arv::array_view<float> & ref_b = b->getX();
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, sci_reseacher, Вы писали:
_>>имеется ввиду вот эта обертка ? или есть еще какой-то wrapper?
J>Да, эта вполне подойдет. А в следующем стандарте или через один будет встроенный std::array_view
Здравствуйте, sci_reseacher, Вы писали:
_>вот здесь теперь можно быть уверенным, что всегда по ссылке ссылкам ref_a, ref_b ... будет доступен актуальный внутренний "array" на чтение без лишних "телодвижений" (копирования приводящего к расходу памяти и времени)?
Да. И нет необходимости создавать константные ссылки, храни их по значению просто.
Здравствуйте, Ops, Вы писали:
Ops>Здравствуйте, uzhas, Вы писали:
U>>или обратись к Стандарту Ops>Не наш случай. Сей адепт интернет-толкований и научного тыка по компиляторам стандарт не признает.
я стандарт избегаю, потому что он написан скорее языком для разработчиков компиляторов, чем для простых пользователей. к тому же очень много исключений, замечаний, нюансов, в которых приходится кропотливо разбираться.
в этом плане ресурс cpp.reference, по-моему, делает хорошее дело — пытается стандарт изложить человеческим языком. другое дело, что у них не всегда это корректно получается сделать.
Здравствуйте, sci_reseacher, Вы писали:
_>>>А как можно вернуть ссылку на std::vector<float> в данной ситуации, когда имеется float *? U>>зачем вам ссылка нужна? какая задача? возвращайте по значению _>нужно сделать наследников D и C класса B, таких, что в одном данные хранятся в std::vector<T>, а в другом классе T* указывает на эти данные.
А нельзя относледовать D от C?
struct B {
virtual const vector<float> & getX() = 0 ;
};
struct D: public B {
vector<float> X;
const vector<float>& getX(){
return X;
}
};
struct C: public D {
float *X;
int size;
void update() {
X = X.data();
size = X.size();
}
};