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