Topic: problem with template and friends


Author: wmm@fastdial.net
Date: 1999/08/04
Raw View
In article <7o5qbi$9cj$1@inf6serv.rug.ac.be>,
  stijn.rammeloo@rug.ac.be wrote:
> I'm encountering the following problem. I boiled it down to the
following code:
>
> template<class T>
> class ref {
> private:
>   friend class T;
>
> Now is my question the following: Is it allowed according to the ANSI
C++
> specification to use a combination of a template and a friend in such
a way

It is not allowed.  7.1.5.3p2 says regarding the name in an
elaborated-type-specifier (like "class T"), "If the identifier
resolves to a typedef-name or a template type-parameter, the
elaborated-type-specifier is ill-formed.  [Note: this implies
that within a class template with a template type-parameter T,
the declaration 'friend class T;' is ill-formed.]"

--
William M. Miller, wmm@fastdial.net
Software Emancipation Technology (www.setech.com)


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: stijn.rammeloo@rug.ac.be
Date: 1999/08/03
Raw View
Hello,

I'm encountering the following problem. I boiled it down to the following code:

>>>>>>>>
#include        <iostream>
#include        <string>

/// A reference counting encapsulation of a pointer.

template<class T>
class ref {
private:
  friend class T;

  T*            _t;
  unsigned int* _n;
protected:
  ref(T* t): _t(t), _n(new unsigned int(1)) {}
public:
  ref(): _t(0), _n(new unsigned int(1)) {}
  ref(const ref<T>& r): _t(r._t), _n(r._n) { ++*_n; }
  ~ref() { if (--*_n) return; delete _t; delete _n; }

  operator      bool() const    { return (_t!=0); }
  T&            operator*() const { return *_t; }
  T*            operator->()    { return _t; }

  ref<T>&               operator=(const ref<T>& r) {
    if (--*_n==0) {
      delete _t; delete _n;
    }
    _t = r._t;  _n=r._n; ++*_n; return *this;  }

  bool          operator==(const ref<T>& r) const {
    if (_t == r._t) return true;
    if (_t)
    if (r._t)
    return (*_t == *r);
    else
    return false;
    // r._t != _t == 0
    return false;
  }

  bool          operator<(const ref<T>& r) const {
    // null is minimal element in this implementation
    if (_t == r._t) return false;
    if (_t)
      if (r._t)
        return (*_t < *r);
      else
        return false;
    // _t == 0, r._t != 0
    return true;
  }
};

class Huge {
  friend class ref<Huge>;

private:
  string                _s;

  Huge(const char* s): _s(s) {}
  ~Huge()       { cerr << "Huge::~Huge()" << endl; }

public:
  friend ostream& operator<<(ostream& os, const Huge& h) {
    return os << h._s;
  }
  const string& s() const { return _s; }

  static ref<Huge> create(const char *s) {
    return ref<Huge>(new Huge(s)); }
};

int
main(int argc,char *argv[])
{
  ref<Huge>     r = Huge::create("c++");

  ref<Huge>     p = r;

  cout << *p << p->s() << endl;
}
<<<<<<<<<<<

When I compile this code-fragment with egcs version 1.1.2 it compiles without
any warnings and works correctly. However when I use the ref class in a
similar way in other situations, the thing generates a SIGSEGV error and
dumps core without -at least for me- a clear indication.

Therefore I upgraded my compiler to the newest egcs version (gcc-2.95) and
hoped for the best (It has better STL and ANSI C++ support besides the
usual bugfixed). However, this new compiler now generates the following fatal
error  while compiling:

>>>>>>>>>>
g++ -Wall -g2 -o test test.C
test.C:9: using template type parameter `T' after `class'
make: *** [test] Error 1
<<<<<<<<<

When I look back to the code this refers to the line:
>>>>>>>>>
friend class T;
<<<<<<<<

Now is my question the following: Is it allowed according to the ANSI C++
specification to use a combination of a template and a friend in such a way
and, if not, how can this problem be alleviated in a way acceptable to ANSI C++.

Thanks in foresee,
Rabbix

PS: You might wonder why I post this message to this newsgroup and not to
the egcs mailing list. Before I'm complaining (sending a bug report ;) to
them, I want yust to make sure I'm not the trouble maker myself. ;)


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Jaakko =?iso-8859-1?Q?J=E4rvi?= <jaakko.jarvi@cs.utu.fi>
Date: 1999/08/04
Raw View
stijn.rammeloo@rug.ac.be wrote:
>
> friend class T;

> Now is my question the following: Is it allowed according to the ANSI C++
> specification to use a combination of a template and a friend in such a way

No, it is ill-formed.
Section 7.1.5.3 (elaborated type specifier) states it clearly.

/Jaakko

--
--- Jaakko Jdrvi, jaakko.jarvi@cs.utu.fi
--- Turku Centre for Computer Science (www.tucs.fi)
--- Lemminkdisenkatu 14 A, FIN-20520 Turku, Finland
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]