На этом шаге мы рассмотрим проблемы использования подмножеств элементов массивов значений.
Прежде чем переходить к рассмотрению вариантов определения подмножеств, следует упомянуть одну общую проблему. Работа с подмножествами элементов в массивах значений организована недостаточно хорошо. Вы легко можете создавать подмножества, но при их использовании вместе с другими подмножествами возникают трудности. К сожалению, практически всегда приходится выполнять явное преобразование типа к valarray. Дело в том, что в стандартной библиотеке C++ не указано, что подмножества поддерживают те же операции, что и массивы значений.
Предположим, нужно вычислить произведение двух подмножеств и присвоить результат третьему подмножеству. Следующее решение не подходит:
// ОШИБКА: отсутствуют преобразования типов
va[std::slice(0,4,3)] = va[std::slice(1,4,3)] * va[std::slice(2,4.3)];
Вместо этого приходится использовать новые операторы преобразования типа (смотри 39 шаг):
va[std::slice(0,4,3)] = static_cast<std::valarray<double> >(va[std::slice(l,4,3)]) * static_cast<std::valarray<double> >(va[std::slice(2,4,3)]);
Подойдет также старый механизм преобразования типа:
va[std::slice(0,4,3)] = std::valarray<double>(va[std::slice(1,4,3)]) * std::valarray<double>(va[std::slice(2,4,3)]);
Ввод таких конструкций - занятие утомительное и чреватое ошибками. Что еще хуже, без хорошей оптимизации работа программы замедлится - при каждом преобразовании создается временный объект, который нужен исключительно для преобразования типа и ни для чего другого.
Следующая шаблонная функция несколько упрощает работу с подмножествами:
// шаблон для преобразования подмножества элементов // массива значений в массив значений template <class T> inline std::valarray <typename T::value_type> VA(const T& valarray_subset) { return std::valarray<typename T::value_type>(valarray_subset); }
При использовании этого шаблона предыдущий пример выглядит так:
va[std::slice(0,4,3)] = VA(va[std::slice(1,4,3)]) *
VA(va[std::slice(2,4,3)]); //OK
Однако проблема снижения быстродействия остается.
При работе с элементами заданного типа также можно воспользоваться простым определением типа:
typedef valarray<double> VAD;
В этом случае запись выглядит так (при условии, что элементы va относятся к типу double):
va[std::slice(0,4б3)] = VAD(va(std::slice(1,4,3)]) *
VAD(va[std::slice(2,4,3)]); // OK
На следующем шаге мы рассмотрим срезы.