template < typename Function, typename Tp >
auto foo(Function fn) -> Tp;
template < typename Tp >
auto foo(Tp fn(Tp)) -> Tp;
On segunda-feira, 30 de setembro de 2013 09:39:09, snk_kid wrote:That would be std::function.
> 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.
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?
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.
- 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.
- 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.
- 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 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.
--
---
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/.
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?
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).
How does that specification differ from what we can get with concepts lite?
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.
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.
template < typename
Tp, Callable(Tp(Tp)) F >
auto foo(F f) -> Tp;
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?
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?
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.
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.
template < typename
Tp, Callable(Tp(Tp)) F >
auto foo(F f) -> Tp;
Now, I urge you to take a look at the concepts-lite proposal and see if it
matches your needs. I think it does.