"Мюррэй Хилл, Бьярн Страустрап. Язык С++" - читать интересную книгу автора

return sum;
}

Одним из особенно полезных аспектов механизма friend является то,
что функция может быть другом двух и более классов. Чтобы увидеть
это, рассмотрим определение vector и matrix, а затем определение
функции умножения (см. #с.8.8).

1.16 Обобщенные Вектора

"Пока все хорошо," - можете сказать вы, - "но я хочу, чтобы один
из этих векторов был типа matrix, который я только что определил."
К сожалению, в C++ не предусмотрены средства для определения класса
векторов с типом элемента в качестве параметра. Один из способов -
продублировать описание и класса, и его функций членов. Это не
идеальный способ, но зачастую вполне приемлемый.
Вы можете воспользоваться препроцессором (#4.7), чтобы
механизировать работу. Например, класс vector - упрощенный вариант
класса, который можно найти в стандартном заголовочном файле. Вы
могли бы написать:

#include

declare(vector,int);

main()
{
vector(int) vv(10);
vv[2] = 3;
vv[10] = 4; // ошибка: выход за границы
}

Файл vector.h таким образом определяет макросы, чтобы
declare(vector,int) после расширения преврашался в описание класса
vector, очень похожий на тот, который был определен выше, а
implement(vector,int) расширялся в определение функций этого
класса. Поскольку implement(vector,int) в результате расширения
превращается в определение функций, его можно использовать в
программе только один раз, в то время как declare(vector,int)
должно использоваться по одному разу в каждом файле, работающем с
этим типом целых векторов.

- стр 44 -

declare(vector,char);
//...
implement(vector,char);

даст вам отдельный тип "вектор символов". Пример реализации
обобщенных классов с помощью макросов приведен в #7.3.5.