Как унифицировать доступ к членам класса, когда их присутствие необязательно?C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Как унифицировать доступ к членам класса, когда их присутствие необязательно?

Сообщение Anonymous »


Processing large amounts of data (gigabytes) I use indexes to data arrays. Since access to data could lead to cache inefficiency, I want to cache some data from array together with the index which gives dramatic speedup for operations through indexes.

The amount of cached data is compile-time choice which should include zero amount of cache data. I have large amount of indexes, so in this case I don’t want to pay for extra “empty” element like std::array does, for example.

My first idea was to introduce a dummy static std::array in the specialization for the struct (demo):

#include using data_type = int; template struct ExtendableIndex { std::size_t index; std::array data; }; template struct ExtendableIndex { std::size_t index; constexpr static std::array data; // Dummy static object to make access to data transparent }; constexpr std::array ExtendableIndex::data; constexpr std::size_t cache_length = 0; // Can be set to any cache size including 0 using DefaultIndex = ExtendableIndex; void data_user(const DefaultIndex& index) { auto value = index.data.begin(); // -> this won't compile for ExtendableIndex without dummy static object } int main() { ExtendableIndex index_one; data_user(index_one); } which works fine and has the advantage of transparency for all data_user-type algorithms in work with data field regardless of the presence of real data.

Aedoro in his answer to my question What is the approach to handle optional class members? provided much better solutions (demo):

#include using data_type = int; template class ExtendableIndex { public: constexpr static std::size_t data_size = _data_size; data_type& at(std::size_t idx) { return data[idx]; } std::size_t index; std::array data; }; template class ExtendableIndex { public: constexpr static std::size_t data_size = 0; data_type& at(std::size_t idx); std::size_t index; }; using DefaultIndex = ExtendableIndex; class DataUser { public: void process(DefaultIndex& index) { if constexpr (DefaultIndex::data_size > 0) { // auto value = index.data[0]; // -> this fails to compile auto value = index.at(0); // -> but this slight workaround solves the issue, `at()` is not implemented and thats OK. } } template void process_template(ExtendableIndex& index) { if constexpr (DefaultIndex::data_size > 0) { auto value = index.data[0]; // -> this compiles even if index.data doesn't exist when 'process' is a template } } }; int main() { DataUser r; ExtendableIndex index_zero; r.process(index_zero); r.process_template(index_zero); ExtendableIndex index_one; r.process_template(index_one); } which avoid creation of dummy static member and solves the task either with a function or with making data_user functions templates. I like his solution and still consider it much better than mine, but it lacks the transparency of my solution. When it comes to large data_user with extensive usage of data field, I have to write many if constexpr to make different code branches and this additionally hits complex conditions which rely on lazy evaluation of || and ‘&&` operations.

The question is, is there a third way? Namely, could this be solved transparently like in my case, without dummy static object and preferably without wrapping access to data field in a separate method?

I know that one of correct answers would be to make functional decomposition for data_user functions, extract code which works with data and make template with if constexpr, but sometimes it is hard and leads to code duplication, anyway if I want to keep lazy evaluation of || and ‘&&` operations.


Источник: https://stackoverflow.com/questions/780 ... s-optional
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»