[Release b] <t4m_bug_templ_over> Mon Jun 28 12:49:25 WEST 2004 In the current release of tendra4minix (a), after fixing <t4m_bug_applyfunctempl>, the program templ_over.C produces this error, "templ_over.C", line 12: Error: [ISO 5.6]: Operands of binary '*' should be arithmetic, not 'Hola < T >' and 'int'. Of course, the problem disappears when 'adios(const T, const T)' is not a template function (see templ_over_e.C). The origin of this problem lies in the code that resolves the overloading of 'operator *'. When considering candidate 'template <class T> Hola<T> Hola<T>::operator * (T)', the compiler must decide if there is a conversion sequence from 'int' to 'T'. The function that makes this decision, convert_seq [convert.c], is not intended to work with template parameters, so it just reports that this conversion is impossible. The following tree is a summary of the call trace starting from make_mult_exp [expression.c], make_mult_exp, op = 78 = lex_star, a = h, b = 2 binary_overload, op = 78 = lex_star, t = Hola<T>, s = int overload_candidates, op = 78 = lex_star, t = Hola<T>, s = int koenig_candidates, id = operator*, t = Hola<T>, kind = 3 ... koenig_candidates: returning operator* add_candidates, id = Hola<T> Hola<T>::operator* (T), over = 1, kind = 4 add_candidate, id = Hola<T> Hola<T>::operator* (T), kind = 4 add_candidate: returning add_candidates: returning overload_candidates: returning operator* resolve_overload, replay = 0 plausible_candidate, nargs = 2, func = Hola<T> Hola<T>::operator* (T) plausible_candidate: returning 0 (= plausible) viable_candidate, func = Hola<T> Hola<T>::operator* (T) convert_seq, p->from = Hola<T>, p->to = Hola<T> & convert_seq: returning 96 = CONV_EXACT convert_seq, p->from = int, p->to = T std_convert_seq, p->from = int, p->to = T std_convert_seq: returning 0 = CONV_NONE convert_seq: returning 0 = CONV_NONE viable_candidate: returning 2 (= no. of matched args., should be 3) /* No viable candidates - return most nearly viable */ resolve_overload: returning apply_binary, op = 78 = lex_star, cpy = 0 make_mult_exp, op = 78 = lex_star "templ_over.C", line 12: Error: [ISO 5.6]: Operands of binary '*' should be arithmetic, not 'Hola < T >' and 'int'. make_mult_exp: returning apply_binary: returning binary_overload: returning make_mult_exp: returning The second call to make_mult_exp [expression.c] is made from apply_binary [operator.c], called at the end of binary_overload [operator.c] after making overload_depth++. If overload_depth != 0, then make_mult_exp does not call binary_overload. The error ERR_expr_mul_mul_op is then reported at the end of make_mult_exp. It is tempting to apply the same technique we used in <t4m_bug_arraybound>, that is, to change the conditionals at the beginning of binary_overload, if ( is_templ_type ( t ) ) { MAKE_exp_op ( t, op, a, b, e ) ; return ( e ) ; } if ( is_templ_type ( s ) ) { MAKE_exp_op ( s, op, a, b, e ) ; return ( e ) ; } to use is_templ_depend (= dependent type) instead of is_templ_type (= template parameter), thus deferring overload resolution until instantiation, but this would be catastrophic, since the fact that the template parameter is used to type the resulting expression is crucial for the rest of the functions to work properly (they use the same predicate is_templ_type to check for templates, so this solution will make them miss this condition; see field_op.C and field_op_b.C for a couple of examples that will break if we make this change). Both GCC-2.95.3 (GNU/Linux-2.2.18) and Compaq C++ V6.5-040 (Tru64 UNIX V5.1B) compile this program without problems (but this is probably because they are delaying overload resolution until instantiation). Perhaps we can instruct convert_seq or std_convert_seq [convert.c] to return CONV_EXACT whenever one of the converting types is a template parameter and then, later, cast_args [function.c] (called from apply_func_id [function.c], called from make_func_exp [function.c]) will do the necessary arrangements or report an error if casting is not possible. But I prefer leaving things untouched for the moment, since we can easily fix the program making an explicit cast, return h*(T)2; and anyway overload resolution with templates is a delicate matter as the following example shows. Appendix Mon Jun 28 16:43:20 WEST 2004 In the current release of TenDRA (a), after fixing <t4m_bug_applyfunctempl>, the program templ_over_f.C produces this error, "templ_over_f.C", line 16: Error: [ISO 5.6]: Operands of binary '*' should be arithmetic, not 'Hola < T >' and 'int'. The program templ_over_f.C is similar to templ_over.C, but this time 'operator *' is a function template instead of a member function of a class template. In this case, it is deduce_args [instance.c] which is failing to unify the template parameter against arguments types. This program is difficult to compile even delaying overload resolution until instantiation: this is the error message from Compaq C++ V6.5-040 (Tru64 UNIX V5.1B), cxx: Error: templ_over_f.C, line 16: no operator "*" matches these operands operand types are: Hola<double> * int detected during instantiation of "Hola<T> adios(const T, const T) [with T=double]" return h*2; // 13.3 Overload resolution [over.match] ----------^ cxx: Info: 1 error detected in the compilation of "templ_over_f.C". And this is the error message from GCC-2.95.3 (GNU/Linux-2.2.18), templ_over_f.C: In function `class Hola<double> adios<double>(double, double)': templ_over_f.C:24: instantiated from here templ_over_f.C:16: no match for `Hola<double> & * int' (In fact, I have tried to delay instantiation in TenDRA using the hack mentioned above, and the error message I have got is identical.) Again, there is a simple way to fix the program, just adding an explicit cast to type 'T', return h*(T)2;