Шаг 433.
Библиотека STL.
Числовые типы. Проблемы с подмножествами элементов массивов значений

    На этом шаге мы рассмотрим проблемы использования подмножеств элементов массивов значений.

    Прежде чем переходить к рассмотрению вариантов определения подмножеств, следует упомянуть одну общую проблему. Работа с подмножествами элементов в массивах значений организована недостаточно хорошо. Вы легко можете создавать подмножества, но при их использовании вместе с другими подмножествами возникают трудности. К сожалению, практически всегда приходится выполнять явное преобразование типа к 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

    На следующем шаге мы рассмотрим срезы.




Предыдущий шаг Содержание Следующий шаг