Topic: Pointer to member function with default argument as deduced template parameter


Author: bill@gibbons.org (Bill Gibbons)
Date: Sat, 13 Jan 2001 08:24:04 GMT
Raw View
In article <93ljfv$7n6@dispatch.concentric.net>, "Carl Daniel"
<carl@pixami.com> wrote:

> The following is a summary of a thread from comp.lang.c++.moderated.  I'm
> hoping that by posting it here, maybe the guru's of C++ will notice it &
> weigh in with an opinion :)
>
> -cd
>
>
> The following code compiles without error with MSVC 6.0 SP4, gcc (2.91.66),
> gcc (2.95.2), MWCW, BC++ 5.2 and Comeau C++ (web tryout).  I maintain that
> it should not:
>
> template <class T, typename MF>
> inline void c(T& t, MF mf)
> {
>   (t.*mf)();  // 1
> }
>
> class Y
> {
>   public:
>     void f(int i=0);  // 2
> };
>
> void foo(Y* py)
> {
>   c(*py,&Y::f);  // 3
> }
>
> There should be an "insufficient arguments" error at //1 during the
> instantiation of template function c at //3.  Apparently the default
> argument specified at //2 gets picked up by the compiler & used to avoid the
> error.

This is clearly ill-formed.  At least one compiler, gcc, also allows the
simple non-member function version:

template <typename PF>
inline void c(PF pf)
{
  (*pf)();  // 1
}

void f(int i=0) { }  // 2

void foo()
{
  c(&f);  // 3
}

I can think of a couple of different ways a compiler writer could make this
mistake, but it is definitely a bug in these compilers.

-- Bill Gibbons

---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: "Carl Daniel" <carl@pixami.com>
Date: Fri, 12 Jan 2001 04:55:22 GMT
Raw View
The following is a summary of a thread from comp.lang.c++.moderated.  I'm
hoping that by posting it here, maybe the guru's of C++ will notice it &
weigh in with an opinion :)

-cd


The following code compiles without error with MSVC 6.0 SP4, gcc (2.91.66),
gcc (2.95.2), MWCW, BC++ 5.2 and Comeau C++ (web tryout).  I maintain that
it should not:

template <class T, typename MF>
inline void c(T& t, MF mf)
{
  (t.*mf)();  // 1
}

class Y
{
  public:
    void f(int i=0);  // 2
};

void foo(Y* py)
{
  c(*py,&Y::f);  // 3
}

There should be an "insufficient arguments" error at //1 during the
instantiation of template function c at //3.  Apparently the default
argument specified at //2 gets picked up by the compiler & used to avoid the
error.


"Greg" <gmc333@my-deja.com> wrote in message
news:93dhri$fqv$1@nnrp1.deja.com...
>
> You've declared the function f() to have a default parameter value of
> zero, so it's legal to call it with an empty parameter list. So your
> program will compile. I did with gcc. Commenting out the "= 0" will
> produce the syntax error you're expecting.
>

At the point of the call, the function being called is not known by the
compiler to be a member of Y which has a default parameter, but simply a
member of Y which takes int and returns void.  Consider a generalization of
the problem:

template <class T, typename MF>
inline void c(T& t, MF mf)
{
  (t.*mf)();
}

class Y
{
  public:
    void f(int i=0);
    void g(int j=55);
    void h(int k=255);
};

void foo(Y* py)
{
  c(*py,&Y::f);
  c(*py,&Y::g);
  c(*py,&Y::h);
}


Here there are three calls to 'c' - note that they will all deduce the same
template arguments: <class Y, void (Y::*)(int)>.  The One Definition Rule
says that void c<Y,void (Y::*)(int)(...) must have exactly ONE definition -
which default parameter value will be present in this case?


Another counter-argument... see what happens if you change the code to read:

void foo(Y* py)
{
  c<Y,void(Y::*)(int)>(*py,&Y::f);
}

Should this have changed the meaning of the program?  Did it?


"Michael Kochetkov" <Michael.Kochetkov@trustworks.commmm> wrote in message
news:3a5afc00@news.telekom.ru...
> For the call
> c(*py,&Y::f);
> you provide two type arguments: reference to the object of type Y and the
> pointer to a member of Y of type void(int=0). A compiler will instantiate
> (say) the following declaration:
> void c@@YAXAAVY@@P81@AEXH@Z@Z (Y& t, void (Y::*mf)(int = 0))
> and definition:
> {
>   (t.*mf)();
> }
> The default arguments have no effect on the partial ordering of function
> tempalates. So I believe that default arguments of arguments have no
effect
> on the partial ordering of function tempalates too. And even more: the
> Standard says that default arguments of functions templates are considered
> definitions (and there is a chance that default arguments of arguments of
> functions templates are considered definitions too). So, for the calls
> c(*py,&Y::g) and c(*py,&Y::h) the declaration
> void c@@YAXAAVY@@P81@AEXH@Z@Z (Y& t, void (Y::*mf)(int = 0)) seems to be
OK
> and a compiler just get use of it.

I don't think partial ordering of function templates has anything to do with
this!

As I understand the language, there's no such thing as a template parameter
of type "pointer to void returning function member of class Y which takes
int defaulting to 0" (i.e.  void (Y::*)(int=0)).  Default function
parameters are part of a function declaration - they are NOT a part of the
function's type - nor should they play any role whatsoever in template
instantiation.

"jsvendsen" <jsvendsen@bergen.frisurf.no> wrote in message
news:ro376.2279$k25.27720@news1.oke.nextra.no...
>
> i suspect your reason to claim that this is an error lies in 8.3.6.9
> it states that a default parameter is not part of the function type, and
> assignment to a function pointer with a different parameter list is an
> error. assignment is the key word here. calling a dereferenced function
> pointer does not seem to be explisitly mentioned in 8.6.3.*
>

(I'm looking at the published standard - the paragraph numbers haven't
changed in this area)

8.3.6 (9) is indeed key - default arguments are not part of a functions
type - type is the key concept here - the argument to the template is a
type.

If you look a little further up, in 8.6.3 (3) the standard reads:

"A default argument expression shall be specified only in the
parameter-declaration-clause of a function declaration or in a
template-parameter (14.1).  If it is specified in a
parameter-declaration-clause, it shall not occur within a declarator or
abstract-declarator of a pointer-declaration (footnote 88)".

Footnote 88 reads:
"This means that default arguments cannot appear, for example, in
declarations of pointers to functions, references to functions or typedef
declarations."

Again, back to my argument - the template argument is a type, and it is of
type pointer-to-(member)-function, which 8.6.3 (3) says cannot include
default arguments.

> however. at an earlier point (8.3.6.4 i think, tired tired tired) the
> standard seems to indicate that the ability to detect a default parameter
> value is determined by scope. the type of the function pointer, as you
have
> pointed out, is void (Y::*)(int), complete with scope specification.
>
> it is my conclusion that the compiler, with the ability to determine the
> scope of the function, should indeed call it WITH it's default parameter.
>
> think about it :
>
> - the compiler knows that the function is a member of Y
> - Y knows that the default parameter to the function at the
>   given pointer is 0
> - the compiler obtains the necessary information from Y and calls.
>

The problem is, it's NOT right - the type of the template function in
question should not include the default argument.  The fact that the
compiler remebered the default argument with the template parameter leads
(inescapably) to wrong code: the default argument "built-in" to the template
instantiation is taken from the first use of the template - subsequent uses
of the template could refer to functions with a different default arugments,
or even no default argument(s) at all, and the template would continue to
supply the default from the first use.




---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]