BUG: friend functions (operators?) declared in class template

Peter Wainwright peter.wainwrightATNRPB.org.uk
Thu Sep 16 06:40:00 GMT 1999


The following code fails to compile under gcc-2.95 (redhat Linux 6.0,
compiler compiled by egcs-1.1.1 from gcc-2.95.1.tar.gz). As you can see
it is a fairly standard bit of code for vector geometry. I stripped
out the non-essentials and got down to this program.

If either DOT_PRODUCT or FLOAT_PRODUCT is undefined, the code compiles
OK. If both are defined, I get this error:

g++ -g    -c test2.C -o test2.o
test2.C: In instantiation of `VectN<float,3>':
test2.C:61:   instantiated from here
test2.C:29: invalid use of undefined type `class VectN<float,3>'
test2.C:31: forward declaration of `class VectN<float,3>'
test2.C:29: confused by earlier errors, bailing out

I tried debugging the compiler, and the error message occurs here
#0  cp_error (format=0x82d34a0 "invalid use of undefined type `%#T'") at errfn.c:200
#1  0x822d941 in incomplete_type_error (value=0x8339f78, type=0x8338e9c) at typeck2.c:229
#2  0x825ff20 in complete_type_or_else (type=0x8338e9c, value=0x8339f78) at typeck.c:270
#3  0x8263c6f in build_component_ref (datum=0x8339f78, component=0x8314f34, basetype_path=0x0, protect=1) at typeck.c:2113
#4  0x8264363 in build_x_component_ref (datum=0x8339f78, component=0x8314f34, basetype_path=0x0, protect=1) at typeck.c:2307
#5  0x823fb61 in build_expr_from_tree (t=0x8339f60) at decl2.c:4087
#6  0x82274b3 in tsubst_expr (t=0x8337320, args=0x8339210, complain=1, in_decl=0x0) at pt.c:7229
#7  0x8221d6b in tsubst_friend_function (decl=0x83374e8, args=0x8339210) at pt.c:4432
#8  0x8222e34 in instantiate_class_template (type=0x8338e9c) at pt.c:5059
#9  0x825feb2 in complete_type (type=0x8338e9c) at typeck.c:250
#10 0x820f446 in grokvardecl (type=0x8338e9c, declarator=0x8333558, specbits_in=0xbfffdca0, initialized=1, constp=0, in_namespace=0x0) at decl.c:9063
#11 0x8213e06 in grokdeclarator (declarator=0x8333558, declspecs=0x83188dc, decl_context=NORMAL, initialized=1, attrlist=0x0) at decl.c:11634
#12 0x820c213 in start_decl (declarator=0x8333558, declspecs=0x83188dc, initialized=1, attributes=0x0, prefix_attributes=0x0) at decl.c:7234
#13 0x820fd54 in grokdeclarator (declarator=0x8333558, declspecs=0x83188dc, decl_context=NORMAL, initialized=0, attrlist=0x0) at decl.c:9434
#14 0x820c213 in start_decl (declarator=0x83188c0, declspecs=0x83188dc, initialized=0, attributes=0x0, prefix_attributes=0x0) at decl.c:7234
#15 0x82526c0 in parse_decl (declarator=0x83188c0, specs_attrs=0x83391ac, attributes=0x0, initialized=0, decl=0xbfffdf24) at parse.y:333
#16 0x8256f12 in yyparse () at parse.y:1929
#17 0x804b934 in compile_file (name=0xbfffeae5 "test2.I") at toplev.c:3265
#18 0x804f69b in main (argc=2, argv=0xbfffe834) at toplev.c:5441
#19 0x40030cb3 in __libc_start_main (main=0x804e464 <main>, argc=2, argv=0xbfffe834, init=0x8048dcc <_init>, fini=0x828ede4 <_fini>, rtld_fini=0x4000a350 <_dl_fini>, stack_end=0xbfffe82c) at ../sysdeps/generic/libc-start.c:78

It seems that the friend declaration (of the scalar x vector operator) gets
confused with the declaration of the class method (vector x vector dot
product) and generates the component_ref which requires a complete
type - but we are still in the class definition, hence the error.

The same code works OK under egcs-1.1.1.

===================
#define DOT_PRODUCT
#define FLOAT_PRODUCT

template<class T, int Ndim> class VectN;

#ifdef FLOAT_PRODUCT
template<class T, int Ndim>
extern VectN<T,Ndim> operator*(T x, const VectN<T,Ndim> &v);
#endif


template<class T, int Ndim>
class VectN
{
private:
  T _v[Ndim];
public:
  VectN(void) {}
  VectN(T const *data)
  {
    for (int i=0; i<Ndim; i++) {
      _v[i] = data[i];
    }
  }
#ifdef DOT_PRODUCT
  T operator*(const VectN &v) const;
#endif
#ifdef FLOAT_PRODUCT
  friend VectN operator*<>(T x, const VectN &v);
#endif
};

#ifdef DOT_PRODUCT
template<class T, int Ndim>
inline T
VectN<T,Ndim>::operator*(const VectN &v) const
{
  T sum = 0.0;
  for (int i=0; i<Ndim; i++) {
    sum += _v[i]*v._v[i];
  }
  return sum;
}
#endif

#ifdef FLOAT_PRODUCT
template<class T, int Ndim>
VectN<T,Ndim> operator*(T x, const VectN<T,Ndim> &v)
{
  VectN<T,Ndim> rv;
  for (int i=0; i<Ndim; i++) {
    rv._v[i] = x*v._v[i];
  }
  return rv;
}
#endif

main()
{
  float data[3] = {1.0, 2.0, 3.0};
  VectN<float,3> v(data);
#ifdef FLOAT_PRODUCT
  VectN<float,3> vs = 3.0F*v;
#endif
#ifdef DOT_PRODUCT
  float dp = v*v;
#endif
}
===================


Peter Wainwright
Home: prw@wainpr.demon.co.uk     Work: peter.wainwright@nrpb.org.uk
http://www.wainpr.demon.co.uk    Fax: +44-870-052-3185
Visit the Opera Exchange Homepage at http://www.treda.co.uk/opex/


More information about the Gcc-bugs mailing list