From: Gennaro Prota (gennaro_prota_at_[hidden])
Date: 2002-08-03 12:58:09


On Sat, 3 Aug 2002 08:19:10 -0400, "David Abrahams"
<dave_at_[hidden]> wrote:

>> > What about adding a new config macro, e.g.
>> > BOOST_NO_MULTIPLE_DEFAULT_TEMPLATE_ARGUMENTS, that deals with this?
>> >
>> > <snip...>
>> >
>> > I'm not sure about the situations in which the problem reveals itself,
>> > so maybe the name of the macro isn't even appropriate but, regardless
>> > of the name, I think some macro is useful. Opinions?
>>
>> Looks reasonable, I'll try and add it some time over the next few days
>> unless there are any other comments.
>
>Well, I didn't think I was going to have to say anything, but the name at
>least is crazy. Normally there's no problem in using multiple default
>arguments with that compiler, and we do it all the time in boost libs.
>Possibly this problem occurs only when one default argument expression uses
>the type of another argument with a default?

Neither :-) The issue is that I haven't found any official
documentation that says when the problem occurs.

parameters with 2 defaults, it seems (*seems*!) that, regardless of
whether a default expression references one of the other parameters,
the problem doesn't occur when

a) either the first encountered declaration of the template is a
definition; e.g.:

// ok
//
template <class A = int, class B = A>
class Test {};

// ok too
//
template <class T>
class traits {};

template <class A = int, class B = traits<A> >
class Test {};

b) or the declarations and the definition all give the (same) default
arguments:

// ok
//
template <class A = int, class B = double>
class Test;

template <class A = int, class B = double>
class Test {};

Instead these all give an error at the point of definition ("C2984:
'Test' : template parameters '' and '' do not match"):

// (1)
//
template <class A = int, class B = A>
class Test;

template <class A, class B>
class Test {};

// (2)
//
template <class A, class B>
class Test;

template <class A = int, class B = double>
class Test {};

// (3)
//
template <class T>
class traits {};

template <class A = int, class B = traits<A> >
class Test;

template <class A, class B>
class Test {};

Note also, that this passes:

// 1 default argument - ok
//
template <class A, class B = A>
class Test;

template <class A, class B>
class Test {};

If the above circumscribes the problem correctly, for libraries that
use the classical xxx_fwd.hpp there are at least 3 choices (let's call
M a suitable macro):

1. not using default arguments at all for compiler(s) that have/has
this problem

// in the declaration
# ifdef M
    template <class A, class B>
# else
    template class A = int, class B = traits<A>
#endif
     class Test;

2. Using only the number of defaults that the compiler accepts (well,
it could depend on the compiler but I don't know if there are others
with the same bug)

Example similar to 1.

3. specifying defaults in the definition too:

// in the definition
//
# ifdef M
    template <class A = int, class B = traits<A> >
# else
    template <class A, class B>
# endif
     class Test {};

This has the draw back that eventually a change of the default
arguments has to be done in more than one point, but I wouldn't be
worried for that. For most libraries, changing the default arguments
would break user code. Option 3 is also feasible without any macro, of
course.

In any case, it would be nice if someone that regularly uses VC had
some more information about the problem. Any hints?
 

Genny.