Topic: temlate deduction from default parameter


Author: cwarlich@alcatel-lucent.de (Christof Warlich)
Date: Thu, 12 Apr 2007 17:53:43 GMT
Raw View
Hi,

is there any good reason why template deduction from a default parameter
does not work? E.g., the following does not compile:

template<typename T> void x(const T &t = (int) 0) {
     // do something:
     (void) t;
}

int main(void) {
     x();
}

Thanks,

Christof

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: greghe@pacbell.net (Greg Herlihy)
Date: Fri, 13 Apr 2007 03:42:36 GMT
Raw View


On 4/12/07 10:53 AM, in article 461e38fe$1@news.alcatel.com, "Christof
Warlich" <cwarlich@alcatel-lucent.de> wrote:

> Hi,
>
> is there any good reason why template deduction from a default parameter
> does not work? E.g., the following does not compile:
>
> template<typename T> void x(const T &t = (int) 0) {
>      // do something:
>      (void) t;
> }
>
> int main(void) {
>      x();
> }

The compiler deduces the type of the template parameter from the type of
argument passed to the function call. So in this example, the compiler has
to deduce type "T" from the parameter that was _not_ passed in x's function
call. So the question essentially becomes what is the type of the argument
that is not present in main()'s call to x()?

In C++09x that question may actually have an answer - in the form of a
default template type parameter:

    template < class T = int >
    void x( const T& t = 0 )
    {
         ...
    }

    int main()
    {
        x(); // OK (...someday)
    }

Greg

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Mathias Gaunard" <loufoque@gmail.com>
Date: Thu, 12 Apr 2007 22:54:14 CST
Raw View
On Apr 12, 7:53 pm, cwarl...@alcatel-lucent.de (Christof Warlich)
wrote:
> Hi,
>
> is there any good reason why template deduction from a default parameter
> does not work? E.g., the following does not compile:
>
> template<typename T> void x(const T &t = (int) 0) {
>      // do something:
>      (void) t;
>
> }
>
> int main(void) {
>      x();
>
> }

How could C++ know that it is that template that should be called?
What is there are other overloads of x ?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: cwarlich@alcatel-lucent.de (Christof Warlich)
Date: Fri, 13 Apr 2007 13:37:51 GMT
Raw View
>> template<typename T> void x(const T &t = (int) 0) {
>>      // do something:
>>      (void) t;
>>
>> }
>>
>> int main(void) {
>>      x();
>>
>> }
>
> How could C++ know that it is that template that should be called?
> What is there are other overloads of x ?

I thought this is obvious: The declaration of x() has (int) 0 as
default parameter, so I'd have expected that the call to x() would
instantiate x() for type int and call it with the value 0.

The notation suggested by Greg as an outlook to C++09x would be
fine from my point of view as well, but I would think the above
should work either, as it emphazises the deduction of the type
from its (default) parameter, similar to a real parameter.

Did I miss some important aspect?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: greghe@pacbell.net (Greg Herlihy)
Date: Sat, 14 Apr 2007 05:10:07 GMT
Raw View
On 4/13/07 6:37 AM, in article 461f1c74@news.alcatel.com, "Christof Warlich"
<cwarlich@alcatel-lucent.de> wrote:

>>> template<typename T> void x(const T &t = (int) 0) {
>>>      // do something:
>>>      (void) t;
>>>
>>> }
>>>
>>> int main(void) {
>>>      x();
>>>
>>> }
>>
>> How could C++ know that it is that template that should be called?
>> What is there are other overloads of x ?
>
> I thought this is obvious: The declaration of x() has (int) 0 as
> default parameter, so I'd have expected that the call to x() would
> instantiate x() for type int and call it with the value 0.

A default argument provides a default value for a parameter in a function
call - but it does not provide an argument with a deducible type. Or to put
it another way: the parameter t in function x()'s declaration already has a
specified type: T. So all that a default argument does is to tell the
compiler to initialize t with the int value 0 (whenever no argument is
provided in a function call). Be even with a default value for t, the
compiler still needs to know t's type before it can assign it the default
value (in the case the int value, 0). The following function call helps to
illustrate this distinction between a parameter's type and the value that
may initialize it:

   x<long>(); // long parameter is initialized with the int value 0

> The notation suggested by Greg as an outlook to C++09x would be
> fine from my point of view as well, but I would think the above
> should work either, as it emphazises the deduction of the type
> from its (default) parameter, similar to a real parameter.

No, the compiler must have determined t's type, T, before t can be assigned
a default value, 0. In practical terms, this means that x() must be
instantiated before the default argument can even be considered. But a
function call to x() without any arguments leaves the compiler with no type
with which to instantiate x() (at least not until default type arguments for
function templates come along). Therefore, x<int>() is not instantiated and
does not become a candidate function that could resolve the function call.

To attain the desired behavior in the current C++ language standard, just
implement a "helper" function to forward the call:

    inline void x() { x<int>(0); }

Greg

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: kuyper@wizard.net
Date: Sat, 14 Apr 2007 12:35:04 CST
Raw View
Greg Herlihy wrote:
> On 4/13/07 6:37 AM, in article 461f1c74@news.alcatel.com, "Christof Warlich"
> <cwarlich@alcatel-lucent.de> wrote:
>
> >>> template<typename T> void x(const T &t = (int) 0) {
> >>>      // do something:
> >>>      (void) t;
> >>>
> >>> }
> >>>
> >>> int main(void) {
> >>>      x();
> >>>
> >>> }
> >>
> >> How could C++ know that it is that template that should be called?
> >> What is there are other overloads of x ?

Obviously, this would only be feasible if there were rules that ranked
the possible matching overloads, and if it were undefined behavior if
there were two or more different best matches. The standard provides
plenty of precedent for rules of that kind.

> > I thought this is obvious: The declaration of x() has (int) 0 as
> > default parameter, so I'd have expected that the call to x() would
> > instantiate x() for type int and call it with the value 0.
>
> A default argument provides a default value for a parameter in a function
> call - but it does not provide an argument with a deducible type. Or to put
> it another way: the parameter t in function x()'s declaration already has a
> specified type: T. So all that a default argument does is to tell the
> compiler to initialize t with the int value 0 (whenever no argument is
> provided in a function call). Be even with a default value for t, the
> compiler still needs to know t's type before it can assign it the default
> value (in the case the int value, 0). The following function call helps to
> illustrate this distinction between a parameter's type and the value that
> may initialize it:
>
>    x<long>(); // long parameter is initialized with the int value 0
>
> > The notation suggested by Greg as an outlook to C++09x would be
> > fine from my point of view as well, but I would think the above
> > should work either, as it emphazises the deduction of the type
> > from its (default) parameter, similar to a real parameter.
>
> No, the compiler must have determined t's type, T, before t can be assigned
> a default value, 0. In practical terms, this means that x() must be
> instantiated before the default argument can even be considered. But a
> function call to x() without any arguments leaves the compiler with no type
> with which to instantiate x() (at least not until default type arguments for
> function templates come along). Therefore, x<int>() is not instantiated and
> does not become a candidate function that could resolve the function call.

That's a good description of the way the rules are currently written;
but as far as I can tell, it would have been feasible to write them to
allow type deduction from default arguments. It would require a major
re-write of the type deduction rules, but is there any other reason
why it would be a bad idea? I'm not saying that there's no such
reason; just pointing out that explaining that reason would have been
a better answer to this inquiry than simply explaining what the
current rules are.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: cwarlich@alcatel-lucent.de (Christof Warlich)
Date: Tue, 17 Apr 2007 13:42:04 GMT
Raw View
> That's a good description of the way the rules are currently written;
> but as far as I can tell, it would have been feasible to write them to
> allow type deduction from default arguments. It would require a major
> re-write of the type deduction rules, but is there any other reason
> why it would be a bad idea? I'm not saying that there's no such
> reason; just pointing out that explaining that reason would have been
> a better answer to this inquiry than simply explaining what the
> current rules are.
Thanks for this summary, it perfectly wraps up the intention of my post.
Up to now, the answer to my initial question:

"is there any _good_ reason why template deduction from a default
parameter does not work?"

seems to be that the _current_ rules do not permit it. A more satisfying
answer would have been something like "interesting point, but not
feasable because ....." or "bad idea, because it may cause problems ..."
or (my favorite :-)): "good idea, let's consider it for the future
standard".

Christof

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: greghe@pacbell.net (Greg Herlihy)
Date: Thu, 19 Apr 2007 00:00:15 GMT
Raw View


On 4/17/07 6:42 AM, in article 4624708d$1@news.alcatel.com, "Christof
Warlich" <cwarlich@alcatel-lucent.de> wrote:

> "is there any _good_ reason why template deduction from a default
> parameter does not work?"

Yes. C++2003 prohibited function templates from having default template type
arguments - or anything (such as type deduction from default argument) that
would have provided a similar mechanism.

As it turned out (see
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#226 ) there was
no compelling reason why function templates should not support default type
parameters, so C++2009 will allow them - and does with using the syntax that
already exists for specifying a default template type parameter.

Therefore in C++2009, type deduction from a default function template would
be completely redundant (since C++ already has a much more familiar syntax
for achieving the same result). But the consequences of adding this behavior
would be worse then creating a redundant syntax. Because - once type
deduction is enabled from a default argument - there would be no apparent
mechanism for turning it off. In other words, if a program wants to
initialize a template argument to some specified value - but still require
the program to provide the parameter's type explicitly - then that program
would have lost the ability able to do so.

So in short, type deduction from default function arguments was banned in
the past and would be a counter-productive addition to C++2009.

Greg

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: s.hesp@oisyn.nl ("Sylvester Hesp")
Date: Thu, 19 Apr 2007 10:31:20 GMT
Raw View
"Greg Herlihy" <greghe@pacbell.net> wrote in message
news:C24BFD46.7CB8%greghe@pacbell.net...
> [...]
> Therefore in C++2009, type deduction from a default function template
> would
> be completely redundant (since C++ already has a much more familiar syntax
> for achieving the same result). But the consequences of adding this
> behavior
> would be worse then creating a redundant syntax. Because - once type
> deduction is enabled from a default argument - there would be no apparent
> mechanism for turning it off. In other words, if a program wants to
> initialize a template argument to some specified value - but still require
> the program to provide the parameter's type explicitly - then that program
> would have lost the ability able to do so.

I don't really understand what you're saying.

template<class T>
void foo(T t = 12);

int main()
{
    foo();   // call foo<int>(12), T is deduced from it's default argument
    foo(23.f);  // call foo<float>(23.f), T is deduced from the supplied
argument
    foo<float>();  // call foo<float>(12.f), T is not deduced but
explicitely specified
}

If type deduction from default arguments is enabled, that doesn't
necessarily imply that it's _always_ deduced from it's default argument.
Only when both the argument itself and it's type aren't specified. So I'm
not sure what you mean by "there would be no apparent mechanism for turning
it off".

- Sylvester Hesp


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: kuyper@wizard.net
Date: Thu, 19 Apr 2007 05:49:50 CST
Raw View
Greg Herlihy wrote:
.
> would be worse then creating a redundant syntax. Because - once type
> deduction is enabled from a default argument - there would be no apparent
> mechanism for turning it off. In other words, if a program wants to
> initialize a template argument to some specified value - but still require
> the program to provide the parameter's type explicitly - then that program
> would have lost the ability able to do so.

It seems to me that you can always turn off template argument
deduction from a default function argument by explicitly specifying
the template argument. Could you provide an example to clarify the
problem this would cause?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Greg Herlihy <greghe@pacbell.net>
Date: Thu, 19 Apr 2007 10:39:15 CST
Raw View
On 4/19/07 3:31 AM, in article 46274000$0$329$e4fe514c@news.xs4all.nl,
""Sylvester Hesp"" <s.hesp@oisyn.nl> wrote:
> "Greg Herlihy" <greghe@pacbell.net> wrote in message
> news:C24BFD46.7CB8%greghe@pacbell.net...
>> [...]
>> Therefore in C++2009, type deduction from a default function template
>> would
>> be completely redundant (since C++ already has a much more familiar syntax
>> for achieving the same result). But the consequences of adding this
>> behavior
>> would be worse then creating a redundant syntax. Because - once type
>> deduction is enabled from a default argument - there would be no apparent
>> mechanism for turning it off. In other words, if a program wants to
>> initialize a template argument to some specified value - but still require
>> the program to provide the parameter's type explicitly - then that program
>> would have lost the ability able to do so.
>
> I don't really understand what you're saying.
>
> template<class T>
> void foo(T t = 12);
>
> int main()
> {
>     foo();   // call foo<int>(12), T is deduced from it's default argument
>     foo(23.f);  // call foo<float>(23.f), T is deduced from the supplied
> argument
>     foo<float>();  // call foo<float>(12.f), T is not deduced but
> explicitely specified
> }

In C++2009, the same three functions are supported with a default template
type parameter, like so:

    template <class T = int>
    void foo( T t = 12 );
    ...
    foo();        // #1 OK calls foo<int>(12)
    foo<float>(); // #2 OK calls foo<float(12.0f)
    foo( 23.0f);  // #3 OK calls foo<float>(23.0f)

Now in C++2009, it is possible for a program to "finetune" foo()'s supported
interface, say, by explicitly allowing calls #2 and #3 above - but rejecting
call #1:

    template <class T>
    void foo( T t = 12 );
    ...
    foo();       // #1 Error: type T not deduced
    foo<float>;  // #2 OK calls foo(12.0f)
    foo( 23.0f); // #3 OK calls foo<float>(23.0f)

Now assume for a moment that C++2009 performed type deduction from a default
function argument. So with this hypothetical change, the programmer will
have lost the ability to disable foo() call #1 while still allowing calls #2
and #3 (and would have gained nothing to offset losing this ability).

In other words, a programmer who wants to require foo's callers to supply
either a type or a value - can enforce such a requirement in C++2009. But
with type deduction from a default function argument, the same programmer
would be out of luck: a requirement to supply either a type or a value when
calling foo() would wind up having to allow calls to foo() that supply
neither.

> If type deduction from default arguments is enabled, that doesn't
> necessarily imply that it's _always_ deduced from it's default argument.
> Only when both the argument itself and it's type aren't specified. So I'm
> not sure what you mean by "there would be no apparent mechanism for turning
> it off".

The point is that with type deduction from default arguments enabled, the
type would always be deduced (from somewhere). So there would be no way to
to turn off type deduction when supplying a default function argument. Yet,
as demonstrated above this kind of type deduction is not only not needed, it
is entirely unhelpful. Furthermore type deduction of default function
arguments runs counter to the the purpose of default function arguments as
they were designed (and as they works today). A default function exists to
provide a value for a parameter of a specified type - and to specify
anything about the parameter's type itself. And there is no reason for
C++2009 to lose the ability to make this useful distinction.

Greg

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]