Изучение шаблонных функций в С++

Искусное владение Threading Building Blocks требует знания определённых аспектов С++, таких как шаблонные функции. Джефф Когсвелл (Jeff Cogswell) рассматривает методы, лежащие в основе шаблонных функций, способы их применения и каким образом они связаны с Threading Building Blocks.

Чтобы полностью понять принцип параллельной работы в Threading Building Blocks (TBB), вам следует быть хорошо знакомым с С++, а особенно с тем, как работают шаблоны.

Уже многие годы я замечаю, что по какой-то причине шаблоны кажутся чем-то загадочным, что сбивает с толку новичков. И несмотря на то, что я уверен в своих знаниях С++, и даже написал книги об этом языке, я помню, что сам поначалу сражался с шаблонами. Но после того, как наконец их выучил, я понял, что они не так уж и сложны, и чаще всего проблема заключается в том, как их объясняют.

Я покажу вам принцип работы одного из шаблонов в Threading Building Blocks. Но если вы впервые сталкиваетесь с TBB и хотите улучшить свои знания С++, вот несколько тем, которые вам захочется рассмотреть в дополнение к основам (под "основами" я имею в виду понятие о классах, как создать новый класс, что представляют собой виртуальные функции и т.д.). Вам следует:

  • Понимать, в чем заключается разница между объектами, распределенными на стеке, и объектами, распределенными в куче, и знать, когда нужно вызывать новый объект, а когда удалять.
  • Знать, что представляют собой конструкторы копирования и как они вызываются.
  • Знать, как создать и вызвать операторные функции (как дополнение, вы можете изучить работу операторов потоков ввода-вывода).
  • Иметь отличное представление о ссылках. В С++ кроме концептов значений и указателей, которые были в С, также используются ссылки. Принцип работы ссылок отличается от принципа работы указателей.
  • Иметь отличное представление о шаблонах (с этим я вам помогу в данной статье).
  • Понимать принцип работы деривации по отношению к шаблонам: деривация нешаблонного класса из шаблона, деривация шаблонного класса из шаблона и т.д.
  • Изучить стандартную библиотеку и понять принцип её работы.
  • Загрузить копию стандарта С++.

Что касается последнего пункта в списке, черновые варианты данного стандарта доступны для бесплатной скачки. Они не всегда являются точными, т.к. вполне возможно, что до опубликования конечного варианта, в стандарт были внесены некоторые изменения, но по большей части всё будет совпадать. К примеру, вот один из проектов. А вот конечный вариант. Там вы увидите два официальных документа по стандартам: один стоит $30 и описывает язык, который вам и нужен. Второй же предназначен для языковых процессоров и обойдётся в пару сотен долларов. Возможно, вам потребуется только первый документ за $30. Если Вы серьёзно относитесь к программированию на С++, то цена себя оправдывает. Я прочитал более ранний вариант от корки до корки и убедился, что понял всё, перед тем как написать одну из своих последних книг по С++.


Функции шаблонов

Одним типом шаблонов в Threading Building Blocks является шаблонная функция, которая используется довольно часто, особенно в секции алгоритмов в справочном руководстве. Перед тем как более детально рассматривать шаблоны такого вида, давайте взглянем на упрощенную версию шаблонной функции, которая позволит вам быстрее понять принцип ее работы.

Рассмотрим такую шаблонную функцию:

template <typename T>
void mytemplatefunction(T instance) {
 instance.myfunction();
}

Данная шаблонная функция назвается mytemplatefunction, т.к. она вызывает компонентную функцию mytemplate всего, что в ней указано. Но что можно вставить в данную функцию? Вы можете вставить экземпляр любого объекта, который имеет компонентную функцию myfunction. Классы необязательно должны создаваться из таких же классов; у них просто должна быть компонентная функция myfunction.

Когда компилятор С++ компилирует ваш код, то внутри он создает различные версии mytemplatefunction для каждого типа, который был в неё вставлен - не для каждого объекта, а для каждого типа. Взгляните на эти два класса:

class First {
public:
 void myfunction() {
  cout << "First!" << endl;
 }
};

class Second {
public:
 void myfunction() {
  cout << "Second!" << endl;
 }
};

Мы смогли создать два экземпляра First, три экземпляра Second и вставить любой из них в mytemplatefunction. Компилятор создаст две отдельные версии функции: одну для класса First и одну для класса Second.

Если мы создадим класс Third, у которого нет компонентной функции myfunction, тогда в процессе компиляции мы увидим сообщение об ошибке ещё до запуска программы.

Если вы пользуетесь Visual Studio и хотите удостовериться, что получите две разные функции, установите в своей программе точку прерывания и устраните ошибку. Когда вы дойдёте до точки прерывания, воспользуйтесь интерактивным окном непосредственной отладки (Immediate Window) Visual Studio (его можно найти в меню Отладка -> Окна -> Непосредственная Отладка (Debug Menu -> Windows -> Immediate)) и введите полное уточненное имя функции. Вот скриншот того, что я увидел:

Как можно заметить, две данные функции имеют различные адреса в памяти, а это и значит, что они являются разными.


Что касается Threading Building Blocks

Относительно Threading Building Blocks, это значит, что если мы хотим использовать одну из шаблонных функций, мы должны знать, в каких членах шаблонной функции будут содержаться наши классы. В данном примере mytemplatefunction будет содержать одну функцию myfunction. Но вот что интересно: если взглянуть на заголовок функции отдельно, мы не увидим ничего, что могло бы указывать на необходимый класс. Это можно узнать, только если детально рассмотреть саму функцию или же прочитать документацию. Более того, если вы создадите класс, в котором не будет необходимого компонента, то увидите соответствующее сообщение. Но вы также увидите ошибку в шаблонной функции, где и делается запрос к данной компонентной функции. Другими словами, появится сообщение об ошибке компиляции, оповещающее об ошибке в самом шаблоне. Если вы используете Threading Building Blocks (или другую библиотеку шаблонов), в результате получится ошибка компилятора в библиотеке, с которой вы работаете. Программисты, которые только начинают использовать шаблоны, на данном этапе могут растеряться, т.к. кажется, что проблема в самом шаблоне, а не в их коде, когда на самом деле проблема именно в нём.

Jeff COGSWELL

Версия для печатиВерсия для печати

Рубрики: 

  • 1
  • 2
  • 3
  • 4
  • 5
Всего голосов: 0
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!

Комментарии

Аватар пользователя savely

К.О.? Дальше-то что-то будет?