What is the best way to specify a function pointer of an overloaded function in algorithm?

162 views
Skip to first unread message

Vlad from Moscow

unread,
Sep 29, 2013, 4:22:06 PM9/29/13
to std-dis...@isocpp.org
Before introducing std::initializer_list there was no problem to specify for example std::min in algorithms. For example
 
std::transform( std::begin( a ), std::end( a ), std::begin( b ),
                        std::ostream_iterator<int>( std:;cout, " " ),
                        std::max<int> );
 
Now std::max<int> is ambiguous due to existence of the definition of the same function with parameter std::initializer_list<T>
 
What is the best way to specify the first or the second overloaded function max (or some other function) in algorithms that to distinguish using an "ordinary" type from std::initializer_list. 
 

Daniel Krügler

unread,
Sep 29, 2013, 4:29:58 PM9/29/13
to std-dis...@isocpp.org
2013/9/29 Vlad from Moscow <vlad....@mail.ru>:
> Before introducing std::initializer_list there was no problem to specify for
> example std::min in algorithms. For example
>
> std::transform( std::begin( a ), std::end( a ), std::begin( b ),
> std::ostream_iterator<int>( std:;cout, " " ),
> std::max<int> );
>
> Now std::max<int> is ambiguous due to existence of the definition of the
> same function with parameter std::initializer_list<T>

That's correct, but that is not very unusual given other overloaded
functions where you need to resolve the correct one.

> What is the best way to specify the first or the second overloaded function
> max (or some other function) in algorithms that to distinguish using an
> "ordinary" type from std::initializer_list.

As usual this can be done by a cast to the corresponding function pointer type.

- Daniel

Vlad from Moscow

unread,
Sep 29, 2013, 4:38:00 PM9/29/13
to std-dis...@isocpp.org
So in any case I need in fact to duplicate the function declaration one more time. 

понедельник, 30 сентября 2013 г., 0:29:58 UTC+4 пользователь Daniel Krügler написал:

Vlad from Moscow

unread,
Sep 29, 2013, 4:41:47 PM9/29/13
to std-dis...@isocpp.org
Will it be suitable to use std::function in this case or are there more compact forms?

понедельник, 30 сентября 2013 г., 0:29:58 UTC+4 пользователь Daniel Krügler написал:
2013/9/29 Vlad from Moscow <vlad....@mail.ru>:

Mathias Gaunard

unread,
Sep 29, 2013, 6:02:32 PM9/29/13
to std-dis...@isocpp.org
Something that doesn't exist yet would be what you need.

std::transform( std::begin( a ), std::end( a ), std::begin( b ),
std::ostream_iterator<int>( std:;cout, " " ),
AS_LAMBDA(std::max) );

where AS_PFO is a macro that turns std::max into a polymorphic lambda
that does perfect forwarding.

#define AS_LAMBDA(NAME) []<class... T>(T&& args...) { return
NAME(static_cast<T&&>(args)...); }

Of course I'm not sure the existing polymorphic lambdas even allow
variadic templates like that.

Vlad from Moscow

unread,
Sep 29, 2013, 6:37:59 PM9/29/13
to std-dis...@isocpp.org, mathias...@ens-lyon.org
It is an interesting idea. Unfortunately the code is not compiled by GCC
 

понедельник, 30 сентября 2013 г., 2:02:32 UTC+4 пользователь Mathias Gaunard написал:

Mathias Gaunard

unread,
Sep 29, 2013, 7:13:00 PM9/29/13
to std-dis...@isocpp.org
On 30/09/13 00:37, Vlad from Moscow wrote:
> It is an interesting idea. Unfortunately the code is not compiled by GCC

As I already said, it's not standard yet.
There are patches for GCC if you're interested in testing them.

Vlad from Moscow

unread,
Sep 30, 2013, 1:00:03 AM9/30/13
to std-dis...@isocpp.org, mathias...@ens-lyon.org
Thanks.
 
In fact what you are suggesting is to call the overloaded function explicitly through a lambda expression.

понедельник, 30 сентября 2013 г., 3:13:00 UTC+4 пользователь Mathias Gaunard написал:

Xeo

unread,
Sep 30, 2013, 2:51:08 AM9/30/13
to std-dis...@isocpp.org, mathias...@ens-lyon.org
This is effectively what my proposal would allow, as a language feature (together with some other niceties).
The Concepts Lite proposal has something seemlingly similar for constrained templates, but in the other direction: It resolves the function at pass-time, instead of call-time.

Faisal Vali

unread,
Sep 30, 2013, 8:20:24 AM9/30/13
to std-dis...@isocpp.org
Polymorphic lambdas do allow variadic templates.  The syntax to do the above would be:
#define AS_LAMBDA(NAME) [](auto&& ... args) { return NAME(std::forward<decltype(args)...>(args)...); };

Certainly one can always argue the syntax is not ideal - but I believe there is an example in the standard
that shows how to do something similar.

This should compile and work with the latest clang trunk (no capturing or nested lambdas just yet for polymorphics - but hopefully that should change very soon).
Please let me know if the above as written does or doesn't currently work.

thanks!

Faisal Vali

unread,
Sep 30, 2013, 8:22:43 AM9/30/13
to std-dis...@isocpp.org
Er that should obviously be :

#define AS_LAMBDA(NAME) [](auto&& ... args)
   { return NAME(std::forward<decltype(args)>(args)...); };

Faisal Vali

Mathias Gaunard

unread,
Sep 30, 2013, 1:40:33 PM9/30/13
to std-dis...@isocpp.org
On 30/09/13 14:20, Faisal Vali wrote:
>
>
> On Sun, Sep 29, 2013 at 5:02 PM, Mathias Gaunard
> <mathias...@ens-lyon.org <mailto:mathias...@ens-lyon.org>> wrote:

> #define AS_LAMBDA(NAME) []<class... T>(T&& args...) { return
> NAME(static_cast<T&&>(args)...); }
>
> Of course I'm not sure the existing polymorphic lambdas even allow
> variadic templates like that.
>
>
>
> Polymorphic lambdas do allow variadic templates. The syntax to do the
> above would be:
> #define AS_LAMBDA(NAME) [](auto&& ... args) { return
> NAME(std::forward<decltype(args)...>(args)...); };

Shouldn't the syntax I wrote above work too? (minus the typo, it should
be T&&... args, not T&& args...)

It doesn't appear to work with latest Clang, though your syntax does.

Daniel Krügler

unread,
Sep 30, 2013, 1:55:23 PM9/30/13
to std-dis...@isocpp.org
2013/9/30 Mathias Gaunard <mathias...@ens-lyon.org>:
>> On Sun, Sep 29, 2013 at 5:02 PM, Mathias Gaunard
>> <mathias...@ens-lyon.org <mailto:mathias...@ens-lyon.org>>
>> wrote:
>
>> #define AS_LAMBDA(NAME) []<class... T>(T&& args...) { return
>> NAME(static_cast<T&&>(args)...); }
>>
>> Of course I'm not sure the existing polymorphic lambdas even allow
>> variadic templates like that.
> Shouldn't the syntax I wrote above work too? (minus the typo, it should be
> T&&... args, not T&& args...)

No, the grammar of lambda closures doesn't support it. The member
templates of generic lambda closures can only be expressed via the
special syntax using auto in the parameter declaration clause.

- Daniel

Richard Smith

unread,
Sep 30, 2013, 2:08:20 PM9/30/13
to std-dis...@isocpp.org
On Mon, Sep 30, 2013 at 5:22 AM, Faisal Vali <fai...@gmail.com> wrote:
Er that should obviously be :

#define AS_LAMBDA(NAME) [](auto&& ... args)
   { return NAME(std::forward<decltype(args)>(args)...); };

Slightly improved (with perfect forwading of the return type and forwarding of the exception specification):

#define AS_LAMBDA(NAME) [](auto&& ... args) \
  noexcept(noexcept(NAME(std::forward<decltype(args)>(args...)))) -> decltype(auto) \

--
 
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.
To post to this group, send email to std-dis...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.

Mathias Gaunard

unread,
Sep 30, 2013, 7:22:24 PM9/30/13
to std-dis...@isocpp.org
It was in revision 1 of the proposal, it must have been removed then.
The patches for GCC also seem to implement the full syntax.

Faisal Vali

unread,
Sep 30, 2013, 9:12:39 PM9/30/13
to std-dis...@isocpp.org


On Mon, Sep 30, 2013 at 6:22 PM, Mathias Gaunard <mathias...@ens-lyon.org> wrote:
On 30/09/13 19:55, Daniel Krügler wrote:
2013/9/30 Mathias Gaunard <mathias...@ens-lyon.org>:
On Sun, Sep 29, 2013 at 5:02 PM, Mathias Gaunard

     #define AS_LAMBDA(NAME) []<class... T>(T&& args...) { return
     NAME(static_cast<T&&>(args)...); }

     Of course I'm not sure the existing polymorphic lambdas even allow
     variadic templates like that.
Shouldn't the syntax I wrote above work too? (minus the typo, it should be
T&&... args, not T&& args...)

No, the grammar of lambda closures doesn't support it. The member
templates of generic lambda closures can only be expressed via the
special syntax using auto in the parameter declaration clause.
It was in revision 1 of the proposal, it must have been removed then.
The patches for GCC also seem to implement the full syntax.


Yes it was - and it was also proposed again as a separate paper in Bristol. 
There were good arguments made for and against support for that syntax -
in the end those who happened to be in the room  decided the fate of what
was forwarded for standardization.

I suppose if enough users are eloquent about the advantages of the
template syntax (with resonating use cases)  - or enough gcc-clang
clients request the extension after dependence - I imagine the
clang-stewards might allow/encourage us to add it there too.



 
--

--- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+unsubscribe@isocpp.org.
Reply all
Reply to author
Forward
0 new messages