работа с данными из базового класса
От: anatoly1  
Дата: 26.07.14 12:42
Оценка:
Предположим, есть такая конструкция:

class data_base_t
{
}

class data_t : public data_base_t
{
}

class storage_base_t
{
}

class storage_t : public storage_base_t
{
    some_collection<data_t> m_data;
}


Есть ли какие-нибудь стандартные бииблиотеки для того, чтобы работать с m_data из storage_base_t (само собой там данные должны быть типа data_base_t&) ?
Или самому надо писать?
Re: работа с данными из базового класса
От: Abyx Россия  
Дата: 26.07.14 12:49
Оценка: 4 (1) +1 -1
Здравствуйте, anatoly1, Вы писали:

почитайте про CRTP
In Zen We Trust
Re: работа с данными из базового класса
От: Кодт Россия  
Дата: 26.07.14 12:59
Оценка: 4 (1)
Здравствуйте, anatoly1, Вы писали:

A>Есть ли какие-нибудь стандартные бииблиотеки для того, чтобы работать с m_data из storage_base_t (само собой там данные должны быть типа data_base_t&) ?

A>Или самому надо писать?

boost::ptr_vector ?

Прежде чем искать или писать, определись с ко/контра/инвариантностью типов элементов.
То есть, понятно, что предок не знает про конкретные элементы. Но может ли он записать в контейнер что-то своё, например? Может ли он вообще делать присваивание? (это самая примитивная контравариантность, разрешённая в С++, и по дефолту ведущая к срезке).
Перекуём баги на фичи!
Re[2]: работа с данными из базового класса
От: anatoly1  
Дата: 26.07.14 13:46
Оценка:
Здравствуйте, Abyx, Вы писали:

A>почитайте про CRTP


Хитро.
Но хотелось бы, конечно, решение полокальнее.
Re[2]: работа с данными из базового класса
От: anatoly1  
Дата: 26.07.14 13:48
Оценка:
Здравствуйте, Кодт, Вы писали:

К>boost::ptr_vector ?


Да, вполне возможно.

А чего нибудь наподобие data_accessor_t нету?

template <typename T>
class data_accessor_t
{
public:
    T& operator[] (const int& i)
    {
        return elem(i);
    }

    function<T&(const int&)> elem;
};

class storage_base_t
{
    data_accessor_t<data_base_t> m_data_acs;
};

class storage_t : public storage_base_t
{
public:
    storage_t()
    {
        m_data_acs.elem = [this] (const int& i) -> data_base_t& { return static_cast<data_base_t&>(m_data[i]); }
    }

    vector<data_t> m_data;
};
Re[3]: работа с данными из базового класса
От: Кодт Россия  
Дата: 26.07.14 18:30
Оценка:
Здравствуйте, anatoly1, Вы писали:

A>А чего нибудь наподобие data_accessor_t нету?


Готового — не знаю.
А сделать своё — легко.
template<class T>
class derived_array
{
  char*  data_; //
  size_t step_; // шаг (размер элемента в байтах)
  size_t size_; // размер массива (в элементах)
public:
  template<class U>
  derived_array(U* data, size_t num) : data_((char*)data), size_(num) { STATIC_ASSERT(is_base_and_derived<T,U>::value); }

  size_t size() const { return size_; }
  T& operator [] (size_t i) const { return (T*)(data_ + i*step_); }

  // итератор слепить из boost::iterator_adaptor - как два пальца об асфальт
};


Тут ещё вопрос возникнет — а что нужно в интерфейсе этого фасада к контейнеру.
Только доступ по индексу?
Итераторы STL?
Возможность менять размер (создавая и удаляя элементы фактического типа)?
Перекуём баги на фичи!
Re[4]: работа с данными из базового класса
От: anatoly1  
Дата: 26.07.14 19:45
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Тут ещё вопрос возникнет — а что нужно в интерфейсе этого фасада к контейнеру.

К>Только доступ по индексу?
К>Итераторы STL?
К>Возможность менять размер (создавая и удаляя элементы фактического типа)?

Желательно, конечно, возможностей по максимому.
Потому и спрашиваю про готовые решения: может где-то уже это всё есть.
Re: работа с данными из базового класса
От: saf_e  
Дата: 28.07.14 08:28
Оценка:
Здравствуйте, anatoly1, Вы писали:

A>Предположим, есть такая конструкция:


A>
A>class data_base_t
A>{
A>}

A>class data_t : public data_base_t
A>{
A>}

A>class storage_base_t
A>{
A>}

A>class storage_t : public storage_base_t
A>{
A>    some_collection<data_t> m_data;
A>}
A>


A>Есть ли какие-нибудь стандартные бииблиотеки для того, чтобы работать с m_data из storage_base_t (само собой там данные должны быть типа data_base_t&) ?

A>Или самому надо писать?

Меня бы насторожило, что вы хотите в базовом классе работать с данными наследника, скорее всего что-то не так с архитектурой.

Скорее всего вам просто нужен некий хелпер-класс, или набор внешнего хелпер-апи. storage_base_t подразумевает семейство классов с общим интерфейсом, вот и не надо тащить в него детали реализации.
Re[2]: работа с данными из базового класса
От: anatoly1  
Дата: 28.07.14 10:51
Оценка:
Здравствуйте, saf_e, Вы писали:

_>Меня бы насторожило, что вы хотите в базовом классе работать с данными наследника, скорее всего что-то не так с архитектурой.


Ну в идеале, конечно, хотелось бы нечто вроде:
class storage_base_t
{
    some_collection<data_base_t> m_data;
}

Только в C++ так не получится.
А коллекцию указателей создавать не хочется.
Re[3]: работа с данными из базового класса
От: Кодт Россия  
Дата: 28.07.14 12:48
Оценка: +1
Здравствуйте, anatoly1, Вы писали:

A>Ну в идеале, конечно, хотелось бы нечто вроде:

A>
A>class storage_base_t
A>{
A>    some_collection<data_base_t> m_data;
A>}
A>

A>Только в C++ так не получится.
A>А коллекцию указателей создавать не хочется.

Проблема архитектурная, а не сиплюсплюсная.
Специально пугаю страшными словами: ковариантность, контравариантность, инвариантность.
Особенно остро этот вопрос возникает в яве и дотнете, хотя присущ ООП вообще.

Если же не пугаться, то просто ответь себе и нам:
— кто определяет тип элементов (наследник или база)
— кто наполняет коллекцию
— кто этим наполнением пользуется

И кстати, сколько наследников в иерархии предполагается иметь. И предполагается ли наследование от наследников.


По-хорошему, у наследника должна быть some_collection<data_t> и интерфейс к предку, отдающий some_view<data_base_t> на эту коллекцию.
Что входит в some_view — только size() и operator[], или ещё что-то — сам решай.

Можно ценой некоторого провала производительности сделать коллекцию, которая в рантайме переключается на использование data_t вместо data_base_t, и бьёт по пальцам за запись туда чего-то отличного от data_t.

Можно ценой тщательного мытья рук — и опять же провала производительности — взять полиморфную коллекцию, наподобие boost::ptr_vector.
Вот там все проблемы ко-контра-вариантности вылезут в полный рост.
Перекуём баги на фичи!
Re[4]: работа с данными из базового класса
От: anatoly1  
Дата: 28.07.14 13:17
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Проблема архитектурная, а не сиплюсплюсная.


В сишарпе такой проблемы нет, т.к. там используется pointer semantics (т.е. фактически boost::ptr_vector).

К>Если же не пугаться, то просто ответь себе и нам:

К>- кто определяет тип элементов

наследник

К>- кто наполняет коллекцию


наследник

К>- кто этим наполнением пользуется


база

К>И кстати, сколько наследников в иерархии предполагается иметь.


Как минимум два.

К>И предполагается ли наследование от наследников.


Нет.

К>Можно ценой тщательного мытья рук — и опять же провала производительности — взять полиморфную коллекцию, наподобие boost::ptr_vector.

К>Вот там все проблемы ко-контра-вариантности вылезут в полный рост.

Скорее всего остановлюсь на vector< unique_ptr<data_base_t> >.
Re[3]: работа с данными из базового класса
От: Mr.Delphist  
Дата: 30.07.14 16:58
Оценка:
Здравствуйте, anatoly1, Вы писали:

A>Здравствуйте, Abyx, Вы писали:


A>>почитайте про CRTP


A>Хитро.

A>Но хотелось бы, конечно, решение полокальнее.

А в чём смущение? Идиома не накладывает тяжких ограничений или зависимостей, полная гибкость в реализации — что ещё надо?
Re[4]: работа с данными из базового класса
От: anatoly1  
Дата: 31.07.14 05:33
Оценка:
Здравствуйте, Mr.Delphist, Вы писали:

MD>А в чём смущение? Идиома не накладывает тяжких ограничений или зависимостей, полная гибкость в реализации — что ещё надо?


В том, что владелец объекта storage_base_t (или storage_t) должен тогда тоже быть шаблонным.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.