[C++17][wish-list] first-class function types or function-type constraints

188 views
Skip to first unread message

snk_kid

unread,
Sep 30, 2013, 11:54:53 AM9/30/13
to std-pr...@isocpp.org
Hi, I have a wishlist of features I'd like to see discussed about, explored and maybe pursued to see C++ evolve. I'll try to post them separately to hopefully have them explored a bit.

I'd like to have some kind of true first-class function types or some mechanism of declaring type constraints which specify & document to other programmers what is expected of a callable entity parameter of template function, when you have code like this:

template < typename Function, typename Tp >
auto foo(Function fn) -> Tp;

It's impossible to know what the expected parameter and return types must be without looking at the definition of the function or trying to figure them out from compile-errors, if you're lucky the author may have properly documented what the types are but that's usually not the case especially for projects that are still in flux.

Even with documentation this still isn't as good as having this as part of the type system and having self-documenting code. I wish I could write C++ code something like this:

template < typename Tp >
auto foo(Tp fn(Tp)) -> Tp;

We have function signatures in C++, can we not make into them first-class function types to some extent? If not maybe some mechisim to achieve simlliar results using template constraints while still being readable, self-documenting and able to produce comprehensible error messages when a programmer makes a mistake.

Thiago Macieira

unread,
Sep 30, 2013, 12:22:58 PM9/30/13
to std-pr...@isocpp.org
On segunda-feira, 30 de setembro de 2013 08:54:53, snk_kid wrote:
> Even with documentation this still isn't as good as having this as part of
> the type system and having self-documenting code. I wish I could write C++
> code something like this:
>
> template < typename Tp >
> auto foo(Tp fn(Tp)) -> Tp;

This compiles. So why can't you write C++ code like that?

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358

snk_kid

unread,
Sep 30, 2013, 12:39:09 PM9/30/13
to std-pr...@isocpp.org
It compiles as a pointer/reference to function which is not exactly what I meant or quite wanted, it's not as flexible as the first version of foo.

The first version would allow pointer/reference to function, a lambda expression that does or does not capture lexical scope (closures), or normal struct with a function call operator overloaded.

Thiago Macieira

unread,
Sep 30, 2013, 12:57:13 PM9/30/13
to std-pr...@isocpp.org
On segunda-feira, 30 de setembro de 2013 09:39:09, snk_kid wrote:
> It compiles as a pointer/reference to function which is not exactly what I
> meant or quite wanted, it's not as flexible as the first version of foo.
>
> The first version would allow pointer/reference to function, a lambda
> expression that does or does not capture lexical scope (closures), or
> normal struct with a function call operator overloaded.

That would be std::function.

template < typename Tp >
auto foo(std::function<Tp(Tp)>) -> Tp;

What are the deficiencies you see in std::function that would require making it
a first-class type?

Philipp Stephani

unread,
Sep 30, 2013, 1:35:49 PM9/30/13
to std-pr...@isocpp.org
2013/9/30 Thiago Macieira <thi...@macieira.org>
On segunda-feira, 30 de setembro de 2013 09:39:09, snk_kid wrote:
> It compiles as a pointer/reference to function which is not exactly what I
> meant or quite wanted, it's not as flexible as the first version of foo.
>
> The first version would allow pointer/reference to function, a lambda
> expression that does or does not capture lexical scope (closures), or
> normal struct with a function call operator overloaded.

That would be std::function.

template < typename Tp >
auto foo(std::function<Tp(Tp)>) -> Tp;

What are the deficiencies you see in std::function that would require making it
a first-class type?

std::function is sometimes too slow (but as usual, that has to be proved on a case-by-case basis, otherwise it's premature optimization).
I guess it might be possible to express such a template constraint using some sort of concepts.

snk_kid

unread,
Sep 30, 2013, 2:10:06 PM9/30/13
to std-pr...@isocpp.org
The problems with using library solution such as std::function is:
  • std::function uses heap allocation by default.
  • If a programmer wants to use a custom allocator to avoid using heap allocation the code becomes more verbose and you loose the ability to write a lamda expression inline.
  • Adds indirection and overhead, using lambda expressions or struct with function call operator is more amenable to inline optimizations. Languages features usually give better opportunities for compiler optimizations than library solutions particularly in more complicated expressions and not single/simple use cases.
  • Depending on the implementation, debugging debug builds with std::function makes the call-stack bigger thus harder to debug. For example in VC++2010, if you look at the call-stack of using std::function vs a plain template function parameter in a debug-build. The situation gets worse when you have more complicated expressions involving nesting/composition of std::functions (either directly or indirectly).
  • Potentially increases compile-times, std::function is non-trivial template machinery.
  • Library Solutions usually requires heuristics in tools for the language to understand library implementations of language features.
I see std::function as work-around more than a true solution but I'm willing to accept something that isn't necessary full on first-class functions.

Daniel Krügler

unread,
Sep 30, 2013, 2:15:39 PM9/30/13
to std-pr...@isocpp.org
2013/9/30 snk_kid <korcan....@googlemail.com>:
> The problems with using library solution such as std::function is:
>
> std::function uses heap allocation by default.

This is clearly an incorrect rumor. The intention is to support
small-object-optimization for small callables:

[ Note: Implementations are
encouraged to avoid the use of dynamically allocated memory for small
callable objects, for example,
where f’s target is an object holding only a pointer or reference to
an object and a member function
pointer. —end note ]

- Daniel

Nevin Liber

unread,
Sep 30, 2013, 2:25:42 PM9/30/13
to std-pr...@isocpp.org
To be fair, the last time I looked at the gcc implementation, the small object optimization only had space for a non-capturing lambda, while boost::function had space for a lambda that captured one pointer (such as "this").

In other words, let your library vendor know what you want and why.
--
 Nevin ":-)" Liber  <mailto:ne...@eviloverlord.com(847) 691-1404

snk_kid

unread,
Sep 30, 2013, 2:30:21 PM9/30/13
to std-pr...@isocpp.org
Still is a problem though, since this is not guaranteed for every implementation and if you want to enforce a particular allocation strategy with std::function code becomes verbose since you have to pass an instance of your allocator type to one of the constructors of std::function as far as I'm aware.

A normal template function parameter doesn't have this issue, lambda expressions are stack allocated by default. If there was no difference between the 2 then all of the standard library generic algorithms would or should be using std::function otherwise why aren't they?

Nevin Liber

unread,
Sep 30, 2013, 2:33:14 PM9/30/13
to std-pr...@isocpp.org
On 30 September 2013 13:10, snk_kid <korcan....@googlemail.com> wrote:
The problems with using library solution such as std::function is:
  • Adds indirection and overhead, using lambda expressions or struct with function call operator is more amenable to inline optimizations. Languages features usually give better opportunities for compiler optimizations than library solutions particularly in more complicated expressions and not single/simple use cases.
That doesn't have to be true for types in the standard library, since their behavior is well specified, and a vendor could take advantage of it.
 
  • Depending on the implementation, debugging debug builds with std::function makes the call-stack bigger thus harder to debug.

I've never found "bigger call stack" as the issue with debugging. 
  • For example in VC++2010, if you look at the call-stack of using std::function vs a plain template function parameter in a debug-build. The situation gets worse when you have more complicated expressions involving nesting/composition of std::functions (either directly or indirectly).

As long as you are binding the functions at run time instead of compile time, I fail to see how a different mechanism would be any better.
 
  • Potentially increases compile-times, std::function is non-trivial template machinery.

Unless you have measurements, this is just FUD.  It isn't that complicated.
 
  • Library Solutions usually requires heuristics in tools for the language to understand library implementations of language features.

And it takes a lot longer for tools to adapt to language features.

snk_kid

unread,
Sep 30, 2013, 3:14:59 PM9/30/13
to std-pr...@isocpp.org
  • Depending on the implementation, debugging debug builds with std::function makes the call-stack bigger thus harder to debug.

I've never found "bigger call stack" as the issue with debugging. 

I haven't had much problems personally but I've seen cases with other people tripping up and saying "why!!!", one example was where a one person was using std::function in function parameters a lot instead of using plain template function parameters, another programmer was debugging code and had a gigantic call-stack most of it all coming from implementation layers of different invocations of std::function.

The example was roughly equivalent to nested std::for_each where the function parameter was using std::function (unlike std::for_each). It's definitely a head scratch when you see it, not so much in terms of difficulty but more in terms of why it has to be this way & wtf.

Granted this was a particular implementation of std::function and doesn't necessarily apply to all compiler vendor implementations.

  • For example in VC++2010, if you look at the call-stack of using std::function vs a plain template function parameter in a debug-build. The situation gets worse when you have more complicated expressions involving nesting/composition of std::functions (either directly or indirectly).

As long as you are binding the functions at run time instead of compile time, I fail to see how a different mechanism would be any better.
 

My original intent is a bit more specific than asking for full on first-class functions (all though why not? why don't we discuss the possibility it instead of dismissing it out-right). I'm talking more about a mechanism to to specify and self-document what the parameter and returns type should/must be for a callable entity in a template function and maybe the basis for future versions of C++ which adds full first-class functions.

I don't mean to say get rid of std::function outright, I'm willing to accept it in different cases like data-members and containers but for functions like the standard library generic algorithms where I think it's clear they don't use std::function for performance reasons it would be nice to have the ability to specify a function signature.


Nevin Liber

unread,
Sep 30, 2013, 3:24:45 PM9/30/13
to std-pr...@isocpp.org
On 30 September 2013 14:14, snk_kid <korcan....@googlemail.com> wrote:
  • Depending on the implementation, debugging debug builds with std::function makes the call-stack bigger thus harder to debug.

I've never found "bigger call stack" as the issue with debugging. 

I haven't had much problems personally but I've seen cases with other people tripping up and saying "why!!!", one example was where a one person was using std::function in function parameters a lot instead of using plain template function parameters, another programmer was debugging code and had a gigantic call-stack most of it all coming from implementation layers of different invocations of std::function.

And you think a magic language feature is going to be *easier* to debug, where in all likelihood you'll get no information about what is happening? 

The example was roughly equivalent to nested std::for_each where the function parameter was using std::function (unlike std::for_each). It's definitely a head scratch when you see it, not so much in terms of difficulty but more in terms of why it has to be this way & wtf.

Teach them.  That is the cost of run time binding of functions when you want to allow anything matching a particular callable signature.
 

Granted this was a particular implementation of std::function and doesn't necessarily apply to all compiler vendor implementations.

  • For example in VC++2010, if you look at the call-stack of using std::function vs a plain template function parameter in a debug-build. The situation gets worse when you have more complicated expressions involving nesting/composition of std::functions (either directly or indirectly).

As long as you are binding the functions at run time instead of compile time, I fail to see how a different mechanism would be any better.
 

My original intent is a bit more specific than asking for full on first-class functions (all though why not? why don't we discuss the possibility it instead of dismissing it out-right).

Language features have a much higher bar to overcome.  They are useful for things that cannot be (easily) expressed in the language, but they also have a huge cost as opposed to just adding a library (which anyone can do in the interim).

I don't mean to say get rid of std::function outright, I'm willing to accept it in different cases like data-members and containers but for functions like the standard library generic algorithms where I think it's clear they don't use std::function for performance reasons it would be nice to have the ability to specify a function signature.

How does that specification differ from what we can get with concepts lite?

Thiago Macieira

unread,
Sep 30, 2013, 4:06:58 PM9/30/13
to std-pr...@isocpp.org
On segunda-feira, 30 de setembro de 2013 11:10:06, snk_kid wrote:
> The problems with using library solution such as std::function is:
>
> - std::function uses heap allocation by default.

Where else would it store the information it needs? The std::function object
cannot be arbitrarily big: the user's lambda or functor can be arbitrarily
big, so it needs to use the heap.

> - If a programmer wants to use a custom allocator to avoid using heap
> allocation the code becomes more verbose and you loose the ability to
> write a lamda expression inline.

Also note that std::function is meant to be passed by value and it will be
copied. Adding the allocator to the parameter list would be quite a drawback
(even if it were possible at this time).

> - Adds indirection and overhead, using lambda expressions or struct with
> function call operator is more amenable to inline optimizations.
> Languages features usually give better opportunities for compiler
> optimizations than library solutions particularly in more complicated
> expressions and not single/simple use cases.

I don't see a way around this either. It has to be indirect, since the code
receiving a std::function does not know whether the data being carried is
pointing to a stateless function, bound member function, functor or lambda.

Still, given a good implementation and a good compiler, it should be able to
inline everything. Though, to be honest, I don't think this is an area where
compiler developers should spend too much time on: std::function is meant to
be used where a generic function is required and often in non-inline code.

> - Depending on the implementation, debugging debug builds with
> std::function makes the call-stack bigger thus harder to debug. For
> example in VC++2010, if you look at the call-stack of using std::function
> vs a plain template function parameter in a debug-build. The situation gets
> worse when you have more complicated expressions involving
> nesting/composition of std::functions (either directly or indirectly).

Bad implementations should not be cause for dropping / deprecating a feature.
Only the inability to write a good implementation should be.

> - Potentially increases compile-times, std::function is non-trivial
> template machinery.

True.

> - Library Solutions usually requires heuristics in tools for the
> language to understand library implementations of language features.
>
> I see std::function as work-around more than a true solution but I'm
> willing to accept something that isn't necessary full on first-class
> functions.

What is your true solution? How would you solve some of the problems I
mentioned?

In specific, I really *no* *way* of implementing a generic bound function
pointer without the possibility of allocating memory. Language-only solutions
would require no dynamic memory allocation.

Billy O'Neal

unread,
Sep 30, 2013, 4:09:28 PM9/30/13
to std-proposals
>Still, given a good implementation and a good compiler, it should be able to inline everything
 
I don't see how the compiler could inline that; the function called is not known until run time.

Billy O'Neal
Malware Response Instructor - BleepingComputer.com


--

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

Thiago Macieira

unread,
Sep 30, 2013, 4:23:11 PM9/30/13
to std-pr...@isocpp.org
On segunda-feira, 30 de setembro de 2013 13:09:28, Billy O'Neal wrote:
> I don't see how the compiler could inline that; the function called is not
> known until run time.

void f();
void g(std::function<void(void)> x) { x(); }
void h()
{
g(f);
}

A sufficiently-advanced compiler and library implementation could detect that
the code above simply calls f and could inline everything.

But, like I said, this is not the typical, expected use of std::function. An
inline function like g above is best written with a template, maybe with some
concepts to constrain it.

The typical case is like you said: the called function is not known until
runtime.

snk_kid

unread,
Sep 30, 2013, 4:25:51 PM9/30/13
to std-pr...@isocpp.org

And you think a magic language feature is going to be *easier* to debug, where in all likelihood you'll get no information about what is happening? 

Why are being so aggressive & condescending? anyways my point is the person who used std::function in parameters, if he used normal template function parameters instead. That particular case of the other guy debugging, the only thing you would see is just lambda calls in the call-stack not layers and layers of implementation details of std::function. The reason why the first guy used std::function in the first-place is because he wanted to constrain & self-document what the parameter and return types are of the function parameter is.

Soooo if we had a way to either specify the types of callable-entities or constrain parameter types to particular function signatures then we don't need to use std::function for this particular use-case besides debuggability wasn't the only reason I mentioned.

Language features have a much higher bar to overcome.  They are useful for things that cannot be (easily) expressed in the language, but they also have a huge cost as opposed to just adding a library (which anyone can do in the interim).
 
I don't think this needs to be said it's pretty obvious to anyone but we have our "interim", that was the point of this thread is discuss the potential future. I don't expect this to be easy, quick and needs to be done immediately.
 
How does that specification differ from what we can get with concepts lite?

It doesn't, there's no specification or one only way I'm just describing how it might ideally look like. Is it even possible to describe such a template constraint (to full genericity)? even if it was possible I don't think it would be good and I don't think it would scale well once you start using multiple function parameters and and other types constraints, it will get quite verbose I think.

If you had some kind of first-class function types (like re-purposing function signatures) this would not be an opposing feature from concepts, they would be quite orthogonal.

snk_kid

unread,
Sep 30, 2013, 4:57:11 PM9/30/13
to std-pr...@isocpp.org
I'm talking more about higher-order functions like generic algorithms specifically than the general case of storing function values but we can discuss that too. I don't know if you have looked into the Rust programming language before but they have different types of first-class functions depending on how they be will be allocated & owner-ship semantics.

I guess it would be very similar to how we have capture clauses for lambda expressions today in C++ where we can explicitly specify what & how we capture lexical scope. So in the case of function-types we can explicitly specifying how the closures should be allocated and maybe the owner-ship semantics (kind of like std::unique_ptr, std::shared_ptr, etc).

Nevin Liber

unread,
Sep 30, 2013, 5:02:50 PM9/30/13
to std-pr...@isocpp.org
On 30 September 2013 15:25, snk_kid <korcan....@googlemail.com> wrote:

And you think a magic language feature is going to be *easier* to debug, where in all likelihood you'll get no information about what is happening? 

Why are being so aggressive & condescending?

I thought your idea was about making things easier for run time binding than std::function is.  I, like others here, have no idea how such a thing would work.

And if it isn't about run time binding, then why do you keep bringing up std::function?
 
anyways my point is the person who used std::function in parameters, if he used normal template function parameters instead.

Why would someone do that?  If you care about performance, you stay in template-land; if not, I don't see any way around what std::function does, unless you limit yourself to C function pointers (which you can still do now).
 
That particular case of the other guy debugging, the only thing you would see is just lambda calls in the call-stack not layers and layers of implementation details of std::function. The reason why the first guy used std::function in the first-place is because he wanted to constrain & self-document what the parameter and return types are of the function parameter is.

The template engine will usually constrain this, albeit with horrible error messages when misused.  Concepts are constraints on templates, and will do much better.

But you really have to decide whether you need compile time binding or run time binding.  We cannot help it if people abuse the run time binding mechanism when they don't need it, and I don't see any way to implement what you are asking for at compile time that isn't the equivalent (in terms of work the compiler has to do) of concepts.

But I could be wrong.  Please enlighten me, preferably with concrete code examples instead of vague abstract notions.

Vicente J. Botet Escriba

unread,
Sep 30, 2013, 5:17:06 PM9/30/13
to std-pr...@isocpp.org
Le 30/09/13 17:54, snk_kid a écrit :


I'd like to have some kind of true first-class function types or some mechanism of declaring type constraints which specify & document to other programmers what is expected of a callable entity parameter of template function, when you have code like this:

template < typename Function, typename Tp >
auto foo(Function fn) -> Tp;

It's impossible to know what the expected parameter and return types must be without looking at the definition of the function or trying to figure them out from compile-errors, if you're lucky the author may have properly documented what the types are but that's usually not the case especially for projects that are still in flux.

Even with documentation this still isn't as good as having this as part of the type system and having self-documenting code. I wish I could write C++ code something like this:

template < typename Tp >
auto foo(Tp fn(Tp)) -> Tp;

We have function signatures in C++, can we not make into them first-class function types to some extent? If not maybe some mechisim to achieve simlliar results using template constraints while still being readable, self-documenting and able to produce comprehensible error messages when a programmer makes a mistake.
Hi,

first-class functions could be used to declare function type constraints, but they do much more. first-class functions could be returned by functions, be assigned, and of course called. This is what std::function does as a library class.

If you want just to constraint a function, concepts should allow you to write something like

template < typename Tp, Callable(Tp(Tp)) F >
auto foo(F f) -> Tp;

Is this what you are looking for?

Vicente

snk_kid

unread,
Sep 30, 2013, 5:49:09 PM9/30/13
to std-pr...@isocpp.org
 
I thought your idea was about making things easier for run time binding than std::function is.  I, like others here, have no idea how such a thing would work.

And if it isn't about run time binding, then why do you keep bringing up std::function?

I never even used the words run-time and/or binding, originally I was responding to Thiago who mentioned using std::function instead of plain function template parameters.

snk_kid

unread,
Sep 30, 2013, 6:09:52 PM9/30/13
to std-pr...@isocpp.org
first-class functions could be used to declare function type constraints, but they do much more. first-class functions could be returned by functions, be assigned, and of course called. This is what std::function does as a library class.

If you want just to constraint a function, concepts should allow you to write something like

template < typename Tp, Callable(Tp(Tp)) F >
auto foo(F f) -> Tp;

Is this what you are looking for?
 
Yes this kinda of what I meant, although would type deducation rules still work here since you don't actually use 'Tp' in the parameters of 'foo'.

I'm not quite fond of this solution as it seems like wouldn't scale well to multiple function parameters I mean it would get quite verbose when you have more parameters and other constraints (even constraints for the template parameters used in "Callable").

It would seem nice if we could get something closer to looking like first-class function types which for now aren't really first-class functions but could be the basis and starting point for future versions of C++. We already have a syntax for function signatures.

Thiago Macieira

unread,
Sep 30, 2013, 10:31:41 PM9/30/13
to std-pr...@isocpp.org
On segunda-feira, 30 de setembro de 2013 15:09:52, snk_kid wrote:
> It would seem nice if we could get something closer to looking like
> first-class function types which for now aren't really first-class
> functions but could be the basis and starting point for future versions of
> C++. We already have a syntax for function signatures.

Functions are first-class types.

That's not what you're talking about. You're talking about a generic
"callable", which is nothing more than "we can slap parentheses at the end".

Functors are not functions and you can think of all lambdas except stateless
ones as functors. There's no way a first-class type can match an arbitrary user
type like that.

It sounds to me like all you want is a good concept.

template <typename T>
concept bool MyConcept(T t)
{
requires { t(); }
}

then you can write:
template <typename T> requires MyConcept(T)
void foo(T);

Or simplified first-level:
template <MyConcept T> void foo(T);

Or simplified second-level:
void foo(MyConcept);

With this second type of simplification, we have a template constrained to a
concept behaving much like your examples so far. And the concept can be made
arbitrarily more complex, as needed.

Now, I urge you to take a look at the concepts-lite proposal and see if it
matches your needs. I think it does.

If it doesn't, then make a proposal of what you'd like this new first-class
type to be, to do; where it could be used and where it couldn't. Please
include also how the compiler would materialise it.

snk_kid

unread,
Oct 1, 2013, 6:45:26 AM10/1/13
to std-pr...@isocpp.org
 
Functions are first-class types.

That's not what you're talking about. You're talking about a generic
"callable", which is nothing more than "we can slap parentheses at the end".

C/C++ functions are not first-class entities currently but I'm not here to argue if they are or are not now, I'm trying to start a civil, professional discussion of potentially improving and evolving the language in the future. I don't understand why people are starting to get hostile and condescending.

Functors are not functions and you can think of all lambdas except stateless
ones as functors.

I know what functional objects are and I know how C++ lambda expressions are supposed to be logically equivalent too generated local structs with functional operator overloaded (that does not mean that a compiler has to actually generated code like that).
 

It sounds to me like all you want is a good concept.

template <typename T>
concept bool MyConcept(T t)
{
    requires { t(); }
}

then you can write:
template <typename T> requires MyConcept(T)
void foo(T);

Or simplified first-level:
template <MyConcept T> void foo(T);

Or simplified second-level:
void foo(MyConcept);

With this second type of simplification, we have a template constrained to a
concept behaving much like your examples so far. And the concept can be made
arbitrarily more complex, as needed.

I've already gone over this with Vicente J in the very post you quoted me on but you seem to ignore it completely! Also your version lacks the self-documenting code aspect that Vicente J's version does have since in your example I have to go to the definition of your concept to figure what the required parameter & return types are.

As I've asked Vicente J, I'll say the same to you. Your example may work for simple callable-entities which do not take parameters and have a void return type but as soon as you deal with more complicated callable entities in particular ones which are polymophic this may not work well with automatic type-deduction rules. An example such as Vicente J's:


template < typename Tp, Callable(Tp(Tp)) F >
auto foo(F f) -> Tp;

In this example does this still work with the type deduction rules so programmers do not have explicity instantiate the first template parameter and say what the type of 'Tp' is? none has responded to this question yet.

Now, I urge you to take a look at the concepts-lite proposal and see if it
matches your needs. I think it does.

I'm quite aware of the concept lite proposal. I've even suggested at the very beginning that if some kind of first-class function types aren't feasible then if there was a way to make this work to full genericity with template constraints (and I mean concept lite) then so be it and a concept like this should be incorporated into the standard library as soon as concepts are standardized.

Thiago Macieira

unread,
Oct 1, 2013, 11:25:07 AM10/1/13
to std-pr...@isocpp.org
On terça-feira, 1 de outubro de 2013 03:45:26, snk_kid wrote:
> As I've asked Vicente J, I'll say the same to you. Your example may work
> for simple callable-entities which do not take parameters and have a void
> return type but as soon as you deal with more complicated callable entities
> in particular ones which are polymophic this may not work well with
> automatic type-deduction rules. An example such as Vicente J's:
>
> template < typename Tp, Callable(Tp(Tp)) F >
> auto foo(F f) -> Tp;
>
> In this example does this still work with the type deduction rules so
> programmers do not have explicity instantiate the first template parameter
> and say what the type of 'Tp' is? none has responded to this question yet.

While I'm familiar with the basics of the concepts-lite, I'm not versed enough
to be able to tell what would happen to the above. Besides, there are many
things that may need to be adjusted until 2017.

But suppose the answer were "yes". Suppose that explicit instantiation were
not necessary with concepts. Would that be enough?

And if it's "no", please make a proposal of what you want and how it would
work. I still don't get what you want, despite reading all of your emails.

Billy O'Neal

unread,
Oct 1, 2013, 1:14:39 PM10/1/13
to std-proposals
>However I don't feel this is the most ideal solution for the future evolution of C++, it seems more of workaround stop gap solution. My line of thought is that since we already have function signatures maybe a better solution is too start from here with maybe a basis to evolve C++ with real first-class functions in the future.
 
I'm afraid I don't understand the difference between "first class functions" and the mechanism provided by std::function. Traditional first class functions (e.g. in JavaScript) can be of arbitrary size, which necessitates dynamic memory allocation and virtual dispatch. (Exactly what std::function does) If that's what you want, you opt-in to it using std::function.
 
> In this example does this still work with the type deduction rules so programmers do not have explicity instantiate the first template parameter and say what the type of 'Tp' is? none has responded to this question yet.
 
This is interesting; I suspect a library solution (similar to std::function's interface) is possible, but I'm no template master. The difficulty here is that the type you want is not in fact "any callable of Tp(Tp)", you want "anything callable as if it were Tp(Tp)" -- including things that are not functions, or things where the argument and return type are only *convertible to/from* Tp. That means there has to be the type name of the called type needs to be deduced, not just Tp.
 
This would be the case even with "first class functions" -- they hold on to different stuff, and as a result they have to be different types. And so deducing the type of the function would still be necessary. (std::function works around this by using type erasure to effectively "forget" that type; but that necessitates the virtual calls that you're asking to avoid)
 
I don't think anyone can argue that deducing Tp in the above example is bad, but what kind of syntax would you propose for it? (the original email's syntax conflicts with the syntax for function pointers)

Billy O'Neal
Malware Response Instructor - BleepingComputer.com


Zhihao Yuan

unread,
Oct 1, 2013, 2:36:00 PM10/1/13
to std-pr...@isocpp.org
On Mon, Sep 30, 2013 at 11:54 AM, snk_kid <korcan....@googlemail.com> wrote:
> I'd like to have some kind of true first-class function types or some
> mechanism of declaring type constraints which specify & document to other
> programmers what is expected of a callable entity parameter of template
> function, when you have code like this:
>
> template < typename Function, typename Tp >
> auto foo(Function fn) -> Tp;
>
> It's impossible to know what the expected parameter and return types must be
> without looking at the definition of the function or trying to figure them
> out from compile-errors, if you're lucky the author may have properly
> documented what the types are but that's usually not the case especially for
> projects that are still in flux.
>
> Even with documentation this still isn't as good as having this as part of
> the type system and having self-documenting code. I wish I could write C++
> code something like this:
>
> template < typename Tp >
> auto foo(Tp fn(Tp)) -> Tp;

If I understand correctly, this works

http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3729.html

And it's planned for Fundamental TS.

--
Zhihao Yuan, ID lichray
The best way to predict the future is to invent it.
___________________________________________________
4BSD -- http://4bsd.biz/

Billy O'Neal

unread,
Oct 1, 2013, 4:45:56 PM10/1/13
to std-proposals
>invocation_type<Fn(ArgTypes...)>
 
"Fn" is still named, so argument deduction wouldn't work.

Billy O'Neal
Malware Response Instructor - BleepingComputer.com


Reply all
Reply to author
Forward
0 new messages