Стандарты программирования на С++. 101 правило и рекомендация | страница 116



>// типа T "foo-совместимости", т.е. наличия функции-члена с

>// данным именем, сигнатурой и семантикой

>template

>void Sample1(T t) {

> t.foo();                  // foo - точка настройки

> typename T::value_type x; // Еще один пример: создание

>}                          // точки настройки для поиска

>                           // типа (обычно создается посредством typedef)

Для реализации первого варианта автор >Sample1 должен выполнить следующие действия.

• Вызвать функцию как член. Просто используйте естественный синтаксис вызова функции-члена.

• Документировать точку настройки. Тип должен обеспечить доступную функцию-член foo, которая может быть вызвана с данными аргументами (в данном случае — без аргументов).

Второй вариант представляет собой использование метода "неявного интерфейса", но с функциями, не являющимися членами, поиск которых выполняется с использованием ADL[3](т.е. ожидается, что данная функция находится в пространстве имен типа, для которого выполняется инстанцирование шаблона). Именно эта ситуация и явилась основной побудительной причиной для введения ADL (см. рекомендацию 57). Ваш шаблон рассчитывает на то, что для используемого типа имеется подходящая функция с заданным именем:

>// Вариант 2: Создание точки настройки путем требования от

>// типа T "fоо-совместимости", т.е. наличия функции, не

>// являющейся членом с данным именем, сигнатурой и

>// семантикой, поиск которой выполняется посредством ADL.

>// (Это единственный вариант, при котором не требуется поиск

>// самого типа T.)

>template

>void Samplе2(T t) {

> foo(t);    // foo - точка настройки

> cout << t; // Еще один пример - operator<< с записью в

>}           // виде оператора представляет собой такую же

>            // точку настройки

Для реализации варианта 2 автор >Samplе2 должен выполнить следующие действия.

• Вызвать функцию с использованием неквалифицированного имени (включая использование естественного синтаксиса в случае операторов) и убедиться, что шаблон не имеет функции-члена с тем же именем. В случае шаблонов очень важно, чтобы вызов функции был не квалифицированным (например, не следует писать >SomeNamespace::foo(t)) и чтобы у шаблона не было функции-члена с тем же именем, поскольку в обоих этих случаях поиск, зависящий от аргумента, выполняться не будет, что предотвратит поиск имени в пространстве имен, в котором находится тип >T.

• Документировать точку настройки. Тип должен обеспечить наличие функции, не являющейся членом, которая может быть вызвана с данными аргументами.