SourceForge.net Logo

[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;