У меня есть шаблон класса Foo
.
Я хотел бы реализовать функцию, не являющуюся членом Bar
, которая принимает два Foo
s и возвращает Foo
. Я хочу, чтобы Bar
не был членом, потому что для вызывающих будет более естественно написать Bar (f1, f2)
, чем f1.Bar (f2)
. Я также хочу, чтобы Bar
был встроенным
, потому что вычисления являются тривиальными и частыми.
template <typename T>
inline Foo<T> Bar(const Foo<T> &lhs, const Foo<T> &rhs) {
...
}
Хитрость в том, что Бар
нуждается в доступе к личным данным Foo
. Я бы предпочел не иметь средств доступа к личным данным - нет веских причин открывать личные данные пользователям.Итак, я хотел бы сделать Бар
другом Foo
.
template <typename T>
class Foo {
...
private:
T w, x, y, z;
friend Foo<T> Bar(const Foo<T> &lhs, const Foo<T> &rhs);
};
Вот здесь у меня проблемы. Компилятор жалуется:
Встроенный спецификатор нельзя использовать, когда объявление друга ссылается на специализацию шаблона функции.
Налагается ли это правило стандартом или оно специфично для MSVC ++?
Вот что я пробовал:
Сделать Bar
константной общедоступной функцией-членом, а затем объявить не версия-member, которая просто возвращает lhs.Bar (rhs)
. Это кажется наименее хакерским решением.
Удалите подсказку inline
, зная, что компилятор будет принимать решение о встраивании независимо от подсказки. Значит, это противоречит правилу одного определения? Его все равно нужно будет определить в файле заголовка, потому что это шаблон функции.
Объявите функцию-член с фиктивным типом шаблона:
template
class Foo {
...
private:
T w, x, y, z;
// Обратите внимание, что это объявление фактически не использует Dummy. Он нужен только для того, чтобы
// удовлетворить компилятор.
template
friend Foo Bar (const Foo & lhs, const Foo & rhs);
};
Я не совсем уверен, почему это работает, но компилятору это удовлетворяет.
Есть ли лучшее решение?