сделать другого друга знакомого из шаблона класса - PullRequest
2 голосов
/ 25 февраля 2011
template <typename T> class Foo;    
template <typename T> int g(Foo<T> const&);

template <typename T> class Foo
{
public:
    template <typename U> int f(Foo<U> const& p) const { return p.m; }

    // which friend declaration will allow the above function to compile? The
    // next one doesn't work.
    template <typename U> friend void Foo<U>::template f<T>(Foo<T> const&) const;

    // while this one work for g().
    friend int g<T>(Foo<T> const&);

private:
    int m;
};

template <typename T> int g(Foo<T> const& p) { return p.m; }

// Let's call them
void bar()
{
    Foo<int> fi;
    Foo<double> fd;
    fd.f(fi);
    g(fi);
}

Выше не компилируется ни с g ++, ни с Como. g () здесь, чтобы показать, что я хотел бы сделать с f ().

Например, вот сообщения g ++:

foo.cpp:11: error: invalid use of template-id ‘f<T>’ in declaration of primary template
foo.cpp: In member function ‘int Foo<T>::f(const Foo<U>&) const [with U = int, T = double]’:
foo.cpp:27:   instantiated from here
foo.cpp:17: error: ‘int Foo<int>::m’ is private
foo.cpp:7: error: within this context

и como's:

"ComeauTest.c", line 11: error: an explicit template argument list is not allowed on
          this declaration
      template <typename U> friend void Foo<U>::template f<T>(Foo<T> const&) const;
                                        ^

"ComeauTest.c", line 7: error: member "Foo<T>::m [with T=int]" (declared at line 17)
          is inaccessible
      template <typename U> int f(Foo<U> const& p) const { return p.m; }
                                                                    ^
          detected during instantiation of "int Foo<T>::f(const Foo<U> &)
                    const [with T=double, U=int]" at line 27

2 errors detected in the compilation of "ComeauTest.c".

Варианты, предложенные в сообщениях об ошибках, тоже не были.

Кстати, я знаю очевидную работу вокруг

template <typename U> friend class Foo<U>;

Edit:

14.5.4 / 5 (из n3225, 14.5.3 / 6 в C ++ 98 похож, но следующий текст более понятен в n3225) начинается с

Член шаблона класса может быть объявлен другом не шаблонного класса ...

, что может означать, что член шаблона класса не может быть объявлен другом класса шаблона, но моя первая интерпретация заключалась бы в том, что это предложение было введением для следующих объяснений (в основном они применяются к любой специализации, явной или нет, учитывая что прототип правильный).

Ответы [ 2 ]

0 голосов
/ 26 февраля 2011

Хотя я не уверен на 100%, что это стандартное соответствие, следующий код может быть скомпилирован ideone (gcc-4.3.4) и Comeau online:

template< class >
class Foo {
  int m;
 public:
  template< class U > int f( Foo<U> const& p ) const { return p.m; }
  template< class U > template< class V >
  friend int Foo<U>::f( Foo<V> const& ) const;
};

void bar() {
  Foo<int> fi;
  Foo<double> fd;
  fd.f( fi );
}

Надеюсь, это поможет.1004 *

0 голосов
/ 25 февраля 2011

Я думаю, что вы должны сказать template <> перед объявлением друга, чтобы он знал, что вы связываете специализацию.

РЕДАКТИРОВАТЬ: Я не могу получить ошибку с вашим кодом, даже делая экземпляр извонит g.Можете ли вы опубликовать минимальный набор фактического кода, который вызывает ошибку, вместе с сообщением об ошибке?

...