Дружественные функции шаблона класса

У меня есть шаблон класса 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); 
    }; 
     

Я не совсем уверен, почему это работает, но компилятору это удовлетворяет.

Есть ли лучшее решение?

8
задан Adrian McCarthy 19 February 2013 в 21:13
поделиться