Topic: Generic functor problem


Author: iltchenko@yahoo.com (Andrei Iltchenko)
Date: Wed, 7 Nov 2001 16:10:08 GMT
Raw View
Daniel Frey <daniel.frey@aixigo.de> wrote in message news:<3BE82E7D.DFC379A2@aixigo.de>...

> I tried to write a generic functor class, something along these lines:
>
> // Code 1:
> #include <functional>
>
> template< typename T, T (*f)( const T&, const T& ) > struct functor :
> public std::binary function< T, T, T >
> {
>    T operator()( const T& a, const T& b ) const
>    {
>       return (*f)( a, b );
>    }
> };
>
> The purpose was ( is :) ) to allow the use of functions like std::min as
> functors. But I ran into a stupid problem:
>
> // Code 2:
> #include <algorithm>
>
> int main()
> {
>    &std::min< int >;
> }
>
> These lines (only "Code 2") are a problem for the gcc (2.95.2: internal
> compiler error) and the Comeau Online Compiler ("cannot determine which
> instance of overloaded function "std::min" is intended"). My question
> is: Should the above compile? Is it allowed by the standard to take the
> address of std::min< int > or is there something that I am missing?

In general, it is allowed to take the address of a function template,
a member function template, or a member function of a class template.
The only thing to note here is that the number of contexts in which
such an operation is allowed is limited. The allowable contexts are
listed in 13.4/1, the list in incomplete however, see the pertinent
defect report at
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_defects.html#202

In the light of the above information your code example 'Code 2' is
ill-formed. Moreover, given the way you defined the class template
'functor' in your fist code sample 'Code 1', it is impossible to
instantiate 'functor' with the address of the function template
'std::min' as its second template argument. The reason being the two
function types (those of the second template parameter and the type of
the specialization of 'std::min') will always be different.

If, however, you rewrite the definition of your class template
'functor' to read:

template< typename T, const T& (*f)( const T&, const T& ) >
struct functor :
   public std::binary_function< T, T, T >
{
   T operator()( const T& a, const T& b ) const
   {
      return (*f)( a, b );
   }
};

It will then be possible to produce the desired instantiation:
int  main()
{
   struct functor<int, &std::min >   my_f;
   // or, if you want to provide the template argument explicitly,
   // struct functor<int, &std::min<int> >   my_f;
}


> Bonus question: If a compiler would be used with 'functor' like in Code
> 1, and it could find out that the address is constant, could it replace
> the whole functor< int, std::min< int > >()( 10, 20 ) at compile time?
> Or does the standard require it to use a real function?

A non-type template argument by its very definition has to be a
constant expression, not necessarily an integral constant expression
though. So the compiler knows for sure that "the address is constant".
As to whether it can replace the whole 'functor< int, std::min< int >
>()( 10, 20 )' at compile time, this is implementation specific. Such
an optimization is definately possible. But even if the compiler is
capable of pulling this off, the construct 'functor< int, std::min<
int > >()( 10, 20 )' is not a C++ constant expression.

By the way it is not a problem to write a compile time min/max in C++.
Searching this news group will certainly present you with a few
solutions.


Regards,

Andrei Iltchenko.

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





Author: Daniel Frey <daniel.frey@aixigo.de>
Date: Wed, 7 Nov 2001 18:23:54 GMT
Raw View
Anthony Williams wrote:
>=20
> "Daniel Frey" <daniel.frey@aixigo.de> wrote in message
> >// Code 2:
> >#include <algorithm>
> >
> >int main()
> >{
> >   &std::min< int >;
> >}
> >
> >These lines (only "Code 2") are a problem for the gcc (2.95.2: interna=
l
> >compiler error) and the Comeau Online Compiler ("cannot determine whic=
h
> >instance of overloaded function "std::min" is intended"). My question
> >is: Should the above compile? Is it allowed by the standard to take th=
e
> >address of std::min< int > or is there something that I am missing?
>=20
> The problem comes, because there are two overloaded template compare
> functions:
>=20
> template<class T> const T& min(const T& a, const T& b);
>=20
> template<class T, class Compare>
> const T& min(const T& a, const T& b, Compare comp);
>=20
> Therefore, std::min<int> doesn't uniquely identify either of them --- i=
s it
> a fully-specified instance of the first, or a partially-specified insta=
nce
> of the second?

This was Comeau's problem, right. I meanwhile made it compile with the
gcc by removing the 'std::' - seems gcc has a pretty stupid bug here.
But after changing it, it seems to have no problem with it. I finally
got this:

#include <functional>

template< typename Arg, typename Result, Result (*function)( Arg ) >
struct unary_functor : public std::unary_function< Arg, Result >
{
   Result operator()( Arg arg ) const
   {
      return (*function)( arg );
   }
};

template< typename Arg1, typename Arg2, typename Result, Result
(*function)( Arg1, Arg2 ) >
struct binary_functor : public std::binary_function< Arg1, Arg2, Result
>
{
   Result operator()( Arg1 arg1, Arg2 arg2 ) const
   {
      return (*function)( arg1, arg2 );
   }
};

#include <iostream>
#include <algorithm>

int main()
{
   binary_functor< const int&, const int&, const int&, &std::min > f;
  =20
   std::cout << f( 42, 41 ) << std::endl;
}

> You can sort this with a typedef
>=20
> typedef const int&(*MinFuncType)(const int&,const int&);
> MinFuncType t=3Dstd::min;

The compiler has to cast it to the right type, the above should yield
the same casting as your typedef, shouldn't it? This means, I have a
hopefully well-formed program now. Also, the gcc seems to inline all
calls away, so I am happy with it.

> The compiler is allowed to do anything it likes, provided you cannot te=
ll
> the difference (the as-if rule), so yes it could evaluate the given
> expression at compile time.

>From what I can see, the above solution is ANSI-C++ and should compile
fine. The standard also doesn't prevent optimizations, I also found it
is optimized for the gcc and I'd be interested to hear about other
compilers that take advantage of the compile-time optimization offered
by passing the function through a template parameter, but this is beyond
the scope of comp.std.c++, so I'll stop the discussion here. Thanks for
your work, Anthony.

Regards, Daniel

--
Daniel Frey

aixigo AG - financial training, research and technology
Schlo=DF-Rahe-Stra=DFe 15, 52072 Aachen, Germany
fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99
eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de

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





Author: "Richard Smith" <richard@ex-parrot.com>
Date: Wed, 7 Nov 2001 18:24:57 GMT
Raw View
"Anthony Williams" <anthwil@nortelnetworks.com> wrote in message
news:9satnb$12fd1h$1@ID-49767.news.dfncis.de...
> "Daniel Frey" <daniel.frey@aixigo.de> wrote in message
> news:3BE82E7D.DFC379A2@aixigo.de...

[...]

> >// Code 2:
> >#include <algorithm>
> >
> >int main()
> >{
> >   &std::min< int >;
> >}
> >
> >These lines (only "Code 2") are a problem for the gcc (2.95.2: internal
> >compiler error) and the Comeau Online Compiler ("cannot determine which
> >instance of overloaded function "std::min" is intended"). My question
> >is: Should the above compile? Is it allowed by the standard to take the
> >address of std::min< int > or is there something that I am missing?
>
> The problem comes, because there are two overloaded template compare
> functions:
>
> template<class T> const T& min(const T& a, const T& b);
>
> template<class T, class Compare>
> const T& min(const T& a, const T& b, Compare comp);
>
> Therefore, std::min<int> doesn't uniquely identify either of them --- is
it
> a fully-specified instance of the first, or a partially-specified instance
> of the second?

But this doesn't seem to be the only problem. If I create a non-overloaded
function,

template <class T>
const T& my_min(const T& a, const T& b)
{
  return (b < a) ? b : a;
}

And try to get the address of this:

int main()
{
  &my_min<int>;
}

... I still get errors from both Comeau and gcc:

Comeau 4.2.45.2:
  cannot determine which instance of function template "my_min" is intended
gcc 3.0.1:
  statement cannot resolve address of overloaded function
gcc 2.95.3
  address of overloaded function with no contextual type information

However, my_min<int> now refers to a unique function, not a set of
overloaded functions, and so I would expect the above example to compile.
Or am I missing something?

--
Richard Smith


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





Author: "Andrei Iltchenko" <iltchenko@yahoo.com>
Date: Wed, 7 Nov 2001 18:25:23 GMT
Raw View
"Anthony Williams" <anthwil@nortelnetworks.com> wrote in message
news:9satnb$12fd1h$1@ID-49767.news.dfncis.de...

> "Daniel Frey" <daniel.frey@aixigo.de> wrote in message
> news:3BE82E7D.DFC379A2@aixigo.de...
> >Hello, world!
> >
> >I tried to write a generic functor class, something along these lines:
> >
> >// Code 1:
> >#include <functional>
> >
> >template< typename T, T (*f)( const T&, const T& ) > struct functor :
> >public std::binary_function< T, T, T >
> >{
> >   T operator()( const T& a, const T& b ) const
> >   {
> >      return (*f)( a, b );
> >   }
> >};
> >
> >The purpose was ( is :) ) to allow the use of functions like std::min as
> >functors. But I ran into a stupid problem:
> >
> >// Code 2:
> >#include <algorithm>
> >
> >int main()
> >{
> >   &std::min< int >;
> >}
> >
> >These lines (only "Code 2") are a problem for the gcc (2.95.2: internal
> >compiler error) and the Comeau Online Compiler ("cannot determine which
> >instance of overloaded function "std::min" is intended"). My question
> >is: Should the above compile? Is it allowed by the standard to take the
> >address of std::min< int > or is there something that I am missing?
>
> The problem comes, because there are two overloaded template compare
> functions:
>
> template<class T> const T& min(const T& a, const T& b);
>
> template<class T, class Compare>
> const T& min(const T& a, const T& b, Compare comp);
>
> Therefore, std::min<int> doesn't uniquely identify either of them --- is
it
> a fully-specified instance of the first, or a partially-specified instance
> of the second?

If the reason for the diagnostic were the one you described, the following
code would compile just fine:
#include <algorithm>
int  main()
{   &std::min<int,std::less<int> >;   }

As this time there is only one function template by name 'min' having two
template parameters.

The actual reason for the error is that the context wherein the address of a
(member) function, a (member) function template, or a member function of a
class template is taken shall always specify a target for this operation.
And the type of the target is used by overload resolution in selecting
viable (member) functions, (member) function  template specializations, or
member functions of a class template specialization.


> You can sort this with a typedef
>
> typedef const int&(*MinFuncType)(const int&,const int&);
> MinFuncType t=std::min;

What you effectively suggest here is that the context contain a target.


Regards,

Andrei Iltchenko.



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





Author: "Anthony Williams" <anthwil@nortelnetworks.com>
Date: Thu, 8 Nov 2001 16:13:19 GMT
Raw View
"Andrei Iltchenko" <iltchenko@yahoo.com> wrote in message
news:9sbc9u$btk@news.nl.compuware.com...
> "Anthony Williams" <anthwil@nortelnetworks.com> wrote in message
> news:9satnb$12fd1h$1@ID-49767.news.dfncis.de...
>
> > "Daniel Frey" <daniel.frey@aixigo.de> wrote in message
> > news:3BE82E7D.DFC379A2@aixigo.de...
> > >// Code 2:
> > >#include <algorithm>
> > >
> > >int main()
> > >{
> > >   &std::min< int >;
> > >}
> > >
> > >These lines (only "Code 2") are a problem for the gcc (2.95.2: internal
> > >compiler error) and the Comeau Online Compiler ("cannot determine which
> > >instance of overloaded function "std::min" is intended"). My question
> > >is: Should the above compile? Is it allowed by the standard to take the
> > >address of std::min< int > or is there something that I am missing?
> >
> > The problem comes, because there are two overloaded template compare
> > functions:
> >
> > template<class T> const T& min(const T& a, const T& b);
> >
> > template<class T, class Compare>
> > const T& min(const T& a, const T& b, Compare comp);
> >
> > Therefore, std::min<int> doesn't uniquely identify either of them --- is
> it
> > a fully-specified instance of the first, or a partially-specified
instance
> > of the second?
>
> If the reason for the diagnostic were the one you described, the following
> code would compile just fine:
> #include <algorithm>
> int  main()
> {   &std::min<int,std::less<int> >;   }
>
> As this time there is only one function template by name 'min' having two
> template parameters.
>
> The actual reason for the error is that the context wherein the address of
a
> (member) function, a (member) function template, or a member function of a
> class template is taken shall always specify a target for this operation.
> And the type of the target is used by overload resolution in selecting
> viable (member) functions, (member) function  template specializations, or
> member functions of a class template specialization.

14.8.1p2 says:

"A template argument list may be specified when referring to a
specialization of a function template
...
- when the address of a function is taken, ..."

Here, we are taking the address of the function, so a template argument list
may be specified. There is no reference to a "target".

For argument deduction (as in my example, below), you need a context, which
includes a target for assignment, or a function call, but for explicit
specification you don't.

> > You can sort this with a typedef
> >
> > typedef const int&(*MinFuncType)(const int&,const int&);
> > MinFuncType t=std::min;
>
> What you effectively suggest here is that the context contain a target.

true, hence the template argument list can be omitted in its entirety.

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optical Components Ltd
The opinions expressed in this message are not necessarily those of my
employer



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





Author: "Anthony Williams" <anthwil@nortelnetworks.com>
Date: Thu, 8 Nov 2001 19:08:32 CST
Raw View
"Daniel Frey" <daniel.frey@aixigo.de> wrote in message
news:3BE91A84.7BBB7DD3@aixigo.de...
>Anthony Williams wrote:
>> The problem comes, because there are two overloaded template compare
>> functions:
>>
>> template<class T> const T& min(const T& a, const T& b);
>>
>> template<class T, class Compare>
>> const T& min(const T& a, const T& b, Compare comp);
>>
>> Therefore, std::min<int> doesn't uniquely identify either of them --- is
it
>> a fully-specified instance of the first, or a partially-specified
instance
>> of the second?
>
>This was Comeau's problem, right. I meanwhile made it compile with the
>gcc by removing the 'std::' - seems gcc has a pretty stupid bug here.

The standard library supplied with gcc 2.95.2 is incomplete, and doesn't use
namespace std.

>But after changing it, it seems to have no problem with it. I finally
>got this:
>
>#include <functional>
>
>template< typename Arg1, typename Arg2, typename Result, Result
>(*function)( Arg1, Arg2 ) >
>struct binary_functor : public std::binary_function< Arg1, Arg2, Result
>>
>{
>   Result operator()( Arg1 arg1, Arg2 arg2 ) const
>   {
>      return (*function)( arg1, arg2 );
>   }
>};
>
>#include <iostream>
>#include <algorithm>
>
>int main()
>{
>   binary_functor< const int&, const int&, const int&, &std::min > f;
>
>   std::cout << f( 42, 41 ) << std::endl;
>}
>
>> You can sort this with a typedef
>>
>> typedef const int&(*MinFuncType)(const int&,const int&);
>> MinFuncType t=std::min;
>
>The compiler has to cast it to the right type, the above should yield
>the same casting as your typedef, shouldn't it? This means, I have a
>hopefully well-formed program now. Also, the gcc seems to inline all
>calls away, so I am happy with it.

Looks OK to me.

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optical Components Ltd
The opinions expressed in this message are not necessarily those of my
employer



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





Author: "Andrei Iltchenko" <iltchenko@yahoo.com>
Date: Thu, 8 Nov 2001 19:08:29 CST
Raw View
"Anthony Williams" <anthwil@nortelnetworks.com> wrote in message
news:9sdh4o$12pb09$1@ID-49767.news.dfncis.de...

> > If the reason for the diagnostic were the one you described, the
following
> > code would compile just fine:
> > #include <algorithm>
> > int  main()
> > {   &std::min<int,std::less<int> >;   }
> >
> > As this time there is only one function template by name 'min' having
two
> > template parameters.
> >
> > The actual reason for the error is that the context wherein the address
of
> a
> > (member) function, a (member) function template, or a member function of
a
> > class template is taken shall always specify a target for this
operation.
> > And the type of the target is used by overload resolution in selecting
> > viable (member) functions, (member) function  template specializations,
or
> > member functions of a class template specialization.
>
> 14.8.1p2 says:
>
> "A template argument list may be specified when referring to a
> specialization of a function template
> ...
> - when the address of a function is taken, ..."
>
> Here, we are taking the address of the function, so a template argument
list
> may be specified. There is no reference to a "target".

This is only one part of the whole story, the other part is in 13.4/1. Read
the last sentence before the note.


Regards,

Andrei Iltchenko.



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





Author: "Anthony Williams" <anthwil@nortelnetworks.com>
Date: Fri, 9 Nov 2001 23:38:17 GMT
Raw View
"Andrei Iltchenko" <iltchenko@yahoo.com> wrote in message
news:9secff$t4v@news.nl.compuware.com...
> "Anthony Williams" <anthwil@nortelnetworks.com> wrote in message
> news:9sdh4o$12pb09$1@ID-49767.news.dfncis.de...
>
> > > If the reason for the diagnostic were the one you described, the
> following
> > > code would compile just fine:
> > > #include <algorithm>
> > > int  main()
> > > {   &std::min<int,std::less<int> >;   }
> > >
> > > As this time there is only one function template by name 'min' having
> two
> > > template parameters.
> > >
> > > The actual reason for the error is that the context wherein the
address
> of
> > a
> > > (member) function, a (member) function template, or a member function
of
> a
> > > class template is taken shall always specify a target for this
> operation.
> > > And the type of the target is used by overload resolution in selecting
> > > viable (member) functions, (member) function  template
specializations,
> or
> > > member functions of a class template specialization.
> >
> > 14.8.1p2 says:
> >
> > "A template argument list may be specified when referring to a
> > specialization of a function template
> > ...
> > - when the address of a function is taken, ..."
> >
> > Here, we are taking the address of the function, so a template argument
> list
> > may be specified. There is no reference to a "target".
>
> This is only one part of the whole story, the other part is in 13.4/1.
Read
> the last sentence before the note.

It seems to me that given

template<typename T>
void func(T)
{
}

void func(int)
{
}

func<int> is not the name of an overloaded function, it is a template id
that names a single function, and so 13.4 doesn't apply. However, if we also
had

template<typename T>
void func(T,T)
{}

Then it would name an overloaded function, and 13.4 would apply, and we
would need one of the target types from 13.4p1 in order to resolve the
overload.

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optical Components Ltd
The opinions expressed in this message are not necessarily those of my
employer



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





Author: "Andrei Iltchenko" <iltchenko@yahoo.com>
Date: Sat, 10 Nov 2001 22:10:31 GMT
Raw View
"Anthony Williams" <anthwil@nortelnetworks.com> wrote in message
news:9sg6h4$1435at$1@ID-49767.news.dfncis.de...

> It seems to me that given
>
> template<typename T>
> void func(T)
> {
> }
>
> void func(int)
> {
> }
>
> func<int> is not the name of an overloaded function, it is a template id
> that names a single function, and so 13.4 doesn't apply. However, if we
also
> had
>
> template<typename T>
> void func(T,T)
> {}
>
> Then it would name an overloaded function

What you state here is not quite correct because a template-id by its very
definition has no context dependent meaning.


> , and 13.4 would apply, and we
> would need one of the target types from 13.4p1 in order to resolve the
> overload.

I see what you mean and you are right thinking that way. But the reason I
objected to your first posting has nothing to do with this, it was due to
you stating the following:

> The problem comes, because there are two overloaded template compare
> functions:
>
> template<class T> const T& min(const T& a, const T& b);
>
> template<class T, class Compare>
> const T& min(const T& a, const T& b, Compare comp);
>
> Therefore, std::min<int> doesn't uniquely identify either of them --- is
it
> a fully-specified instance of the first, or a partially-specified instance
> of the second?

And I corrected you saying:

: If the reason for the diagnostic were the one you described, the following
: code would compile just fine:
: #include <algorithm>
: int  main()
: {   &std::min<int,std::less<int> >;   }
:
: As this time there is only one function template by name 'min' having two
: template parameters.

and then I stated the true cause of the error based on 13.4/1. I hope you
now agree that the problem in the original posting was owing to the function
template 'std::min' being overloaded and the poster not providing a target,
which is precisely what I wrote in my correction.


Cheers,

Andrei Iltchenko.





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





Author: Gabriel Dos_Reis <gdosreis@sophia.inria.fr>
Date: Sat, 10 Nov 2001 23:36:14 GMT
Raw View
"Andrei Iltchenko" <iltchenko@yahoo.com> writes:

| "Anthony Williams" <anthwil@nortelnetworks.com> wrote in message
| news:9sg6h4$1435at$1@ID-49767.news.dfncis.de...
|
| > It seems to me that given
| >
| > template<typename T>
| > void func(T)
| > {
| > }
| >
| > void func(int)
| > {
| > }
| >
| > func<int> is not the name of an overloaded function, it is a template id
| > that names a single function, and so 13.4 doesn't apply. However, if we
| also
| > had
| >
| > template<typename T>
| > void func(T,T)
| > {}
| >
| > Then it would name an overloaded function
|
| What you state here is not quite correct because a template-id by its very
| definition has no context dependent meaning.

I'm lost.  Please, could you elaborate on that sentence?

--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr

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





Author: "Andrei Iltchenko" <iltchenko@yahoo.com>
Date: Sun, 11 Nov 2001 11:45:26 GMT
Raw View
"Gabriel Dos_Reis" <gdosreis@sophia.inria.fr> wrote in message
news:xajhes2fer3.fsf@perceval.inria.fr...

> | > It seems to me that given
> | >
> | > template<typename T>
> | > void func(T)
> | > {
> | > }
> | >
> | > void func(int)
> | > {
> | > }
> | >
> | > func<int> is not the name of an overloaded function, it is a template
id
> | > that names a single function, and so 13.4 doesn't apply. However, if
we
> | also
> | > had
> | >
> | > template<typename T>
> | > void func(T,T)
> | > {}
> | >
> | > Then it would name an overloaded function
> |
> | What you state here is not quite correct because a template-id by its
very
> | definition has no context dependent meaning.
>
> I'm lost.  Please, could you elaborate on that sentence?

I was referring to his comments about the same template-id naming one thing
in one context and having a different meaning in another context, which is
incorrect based on 1.6/2.


Regards,

Andrei Iltchenko.



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





Author: "Anthony Williams" <anthwil@nortelnetworks.com>
Date: Tue, 13 Nov 2001 01:44:17 GMT
Raw View
"Andrei Iltchenko" <iltchenko@yahoo.com> wrote in message
news:9sk5el$14m0jf$1@ID-62495.news.dfncis.de...
> "Anthony Williams" <anthwil@nortelnetworks.com> wrote in message
> news:9sg6h4$1435at$1@ID-49767.news.dfncis.de...
>
> > It seems to me that given
> >
> > template<typename T>
> > void func(T)
> > {
> > }
> >
> > void func(int)
> > {
> > }
> >
> > func<int> is not the name of an overloaded function, it is a template id
> > that names a single function, and so 13.4 doesn't apply. However, if we
> also
> > had
> >
> > template<typename T>
> > void func(T,T)
> > {}
> >
> > Then it would name an overloaded function
>
> What you state here is not quite correct because a template-id by its very
> definition has no context dependent meaning.

A template-id is defined in 14.2p1

"template-id:
    template-name < template-argument-list-opt >"

Such a construct can mean different things in different contexts. In this
case, func<int> is ambiguous, as it could mean func<int>(int,int) or
func<int>(int). Given the third case

template<typename T,typename U>
void func(U){}

func<int> could also partially specify func<int,U> for some U, but would
need a target or usage in order for U to be determined. If I specified
func<int,int> then there is (again) only one template that the template-id
could resolve to.

> > , and 13.4 would apply, and we
> > would need one of the target types from 13.4p1 in order to resolve the
> > overload.
>
> I see what you mean and you are right thinking that way. But the reason I
> objected to your first posting has nothing to do with this, it was due to
> you stating the following:
>
> > The problem comes, because there are two overloaded template compare
> > functions:
> >
> > template<class T> const T& min(const T& a, const T& b);
> >
> > template<class T, class Compare>
> > const T& min(const T& a, const T& b, Compare comp);
> >
> > Therefore, std::min<int> doesn't uniquely identify either of them --- is
> it
> > a fully-specified instance of the first, or a partially-specified
instance
> > of the second?
>
> And I corrected you saying:
>
> : If the reason for the diagnostic were the one you described, the
following
> : code would compile just fine:
> : #include <algorithm>
> : int  main()
> : {   &std::min<int,std::less<int> >;   }
> :
> : As this time there is only one function template by name 'min' having
two
> : template parameters.

Which should compile, as std::min<int,std::less<int> > is a template-id that
uniquely identifies a specific instantiation of std::min. This is not in any
way a correction to my original statement. Indeed, after re-reading 14.8.3,
I believe that "&std::min<int>;" is a well-formed statement, since 14.8.3p1
says:

"... For each function template, if the argument deduction and checking
succeeds, the template-arguments (deduced and/or explicit) are used to
instantiate a single function template specialization which is added to the
candidate functions set to be used in overload resolution. If, for a given
function template, argument deduction fails, no such function is added to
the set of candidate functions for that template. ..."

and argument deduction will fail for std::min<class T,class Compare> (as
there is no target), whereas there is no need for argument deduction for
std::min<class T>, since the single argument is explicitly specified.

> and then I stated the true cause of the error based on 13.4/1. I hope you
> now agree that the problem in the original posting was owing to the
function
> template 'std::min' being overloaded and the poster not providing a
target,
> which is precisely what I wrote in my correction.

Given that it is overloaded, had the poster provided a target, it would not
have been ambiguous. I agree with this, and always have done. However, I
don't think this is the whole issue, as you seem to be arguing that the mere
existence of overloaded templates means that none of them can be identified
with a template-id, even if such a template-id could only apply to one of
the overloads, and I disagree with this.

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optical Components Ltd
The opinions expressed in this message are not necessarily those of my
employer



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





Author: Daniel Frey <daniel.frey@aixigo.de>
Date: Tue, 6 Nov 2001 18:42:18 GMT
Raw View
Hello, world!

I tried to write a generic functor class, something along these lines:

// Code 1:
#include <functional>

template< typename T, T (*f)( const T&, const T& ) > struct functor :
public std::binary_function< T, T, T >
{
   T operator()( const T& a, const T& b ) const
   {
      return (*f)( a, b );
   }
};

The purpose was ( is :) ) to allow the use of functions like std::min as
functors. But I ran into a stupid problem:

// Code 2:
#include <algorithm>

int main()
{
   &std::min< int >;
}

These lines (only "Code 2") are a problem for the gcc (2.95.2: internal
compiler error) and the Comeau Online Compiler ("cannot determine which
instance of overloaded function "std::min" is intended"). My question
is: Should the above compile? Is it allowed by the standard to take the
address of std::min< int > or is there something that I am missing?

Bonus question: If a compiler would be used with 'functor' like in Code
1, and it could find out that the address is constant, could it replace
the whole functor< int, std::min< int > >()( 10, 20 ) at compile time?
Or does the standard require it to use a real function? (This sound
strange, but I don't know how to express it clearer, sorry...)

Regards, Daniel

--
Daniel Frey

aixigo AG - financial training, research and technology
Schlo=DF-Rahe-Stra=DFe 15, 52072 Aachen, Germany
fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99
eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de

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





Author: "Anthony Williams" <anthwil@nortelnetworks.com>
Date: Wed, 7 Nov 2001 10:53:49 GMT
Raw View
"Daniel Frey" <daniel.frey@aixigo.de> wrote in message
news:3BE82E7D.DFC379A2@aixigo.de...
>Hello, world!
>
>I tried to write a generic functor class, something along these lines:
>
>// Code 1:
>#include <functional>
>
>template< typename T, T (*f)( const T&, const T& ) > struct functor :
>public std::binary_function< T, T, T >
>{
>   T operator()( const T& a, const T& b ) const
>   {
>      return (*f)( a, b );
>   }
>};
>
>The purpose was ( is :) ) to allow the use of functions like std::min as
>functors. But I ran into a stupid problem:
>
>// Code 2:
>#include <algorithm>
>
>int main()
>{
>   &std::min< int >;
>}
>
>These lines (only "Code 2") are a problem for the gcc (2.95.2: internal
>compiler error) and the Comeau Online Compiler ("cannot determine which
>instance of overloaded function "std::min" is intended"). My question
>is: Should the above compile? Is it allowed by the standard to take the
>address of std::min< int > or is there something that I am missing?

The problem comes, because there are two overloaded template compare
functions:

template<class T> const T& min(const T& a, const T& b);

template<class T, class Compare>
const T& min(const T& a, const T& b, Compare comp);

Therefore, std::min<int> doesn't uniquely identify either of them --- is it
a fully-specified instance of the first, or a partially-specified instance
of the second?

You can sort this with a typedef

typedef const int&(*MinFuncType)(const int&,const int&);
MinFuncType t=std::min;

>Bonus question: If a compiler would be used with 'functor' like in Code
>1, and it could find out that the address is constant, could it replace
>the whole functor< int, std::min< int > >()( 10, 20 ) at compile time?
>Or does the standard require it to use a real function? (This sound
>strange, but I don't know how to express it clearer, sorry...)

The compiler is allowed to do anything it likes, provided you cannot tell
the difference (the as-if rule), so yes it could evaluate the given
expression at compile time.

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optical Components Ltd
The opinions expressed in this message are not necessarily those of my
employer



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