Function template as parameter - c++

I have been trying to implement in C++11 the function map from Python. It seems to work for any kind of callable objet, but I have to specify the template type parameter if I want it to work with function templates. Example:
#include <iostream>
#include <list>
template<typename T>
T abs(T x)
{
return x < 0 ? -x : x;
}
int main()
{
std::list<int> li = { -1, -2, -3, -4, -5 };
for (auto i: map(&abs<int>, li))
{
std::cout << i << std::endl;
}
}
It works fine, but I would like it to deduce the int parameter from the second argument of the function, and hence be able to write:
for (auto i: map(&abs, li))
{
std::cout << i << std::endl;
}
My map function is written as:
template<typename Callable, typename Container>
auto map(const Callable& function, Container&& iter)
-> MapObject<Callable, Container>
{
return { function, std::forward<Container>(iter) };
}
where MapObject is part of the implmentation and not a real problem here. How could I change its definition so that the template type of the Callable object can be deduced from the Container object? For example, how can map know that we have to use abs<int> for a given abs when a list<int> is given?

It works fine, but I would like it to deduce the int parameter from the second argument of the function, and hence be able to write:
for (auto i: map(&abs, li))
{
std::cout << i << std::endl;
}
The problem is that abs is not a function, but a function template, and thus there is no address-of abs, although there is &abs<int>, since abs<int> (specialization) is indeed a function (generated from a template).
Now the question is what you really want to solve, and in particular you must realize that C++ is a statically typed language where python is a dynamically typed language. It is unclear to me what you are trying to achieve here on different levels. For example, the function map in python has an equivalent in std::transform in C++:
a = [ 1, 2, 3 ]
a = map(lambda x: 2*x, a)
std::vector<int> v{1,2,3};
std::transform(v.begin(),v.end(),v.begin(),[](int x){ return 2*x; });
Where I have cheated slightly because in python it will create a different container yet in C++ transform works at the iterator level and knows of no container, but you can get the same effect similarly:
std::vector<int> v{1,2,3};
std::vector<int> result;
// optionally: result.reserve(v.size());
std::transform(v.begin(),v.end(),
std::back_inserter(result),
[](int x) { return 2*x; });
I'd advice that you learn the idioms in the language rather than trying to implement idioms from other languages...
BTW, if you are willing to have the user specify the type of the functor that is passed to the map function, then you can just pass the name of the template and let the compiler figure out what specialization you need:
template <typename Container>
auto map(Container && c,
typename Container::value_type (*f)(typename Container::value_type))
-> MapObject<Callable<T>,Container>;
template <typename T>
T abs(T value);
int main() {
std::vector<int> v{1,2,3,4};
map(v,abs);
}
This is less generic than what you were trying to do, as it only accepts function pointers and of concrete type (this is even less generic than std::transform) and it works as when the compiler sees abs (without the &) it will resolve it to the template, and thus to the set of specializations. It will then use the expected type to select one specialization and pass it in. The compiler will implicitly do &abs<int> for you in this case.
Another more generic alternative is not using functions, but functors. With this in mind you can define abs as:
struct abs {
template <typename T>
T operator()(T t) { ...}
};
And then pass a copy of the functor in instead of the function pointer. There is no need to determine the overload to be used where you pass the object abs into the map function, only when it is used. The caller side would look like:
for (auto& element : map(container,abs()))
Where the extra set of parenthesis is creating an object of type abs and passing it in.
Overall, I would try to avoid this. It is a fun thing to do, and you can probably get to a good solution, but it will be hard and require quite a bit of c++ expertise. Because it is not supported by the language, you will have to design something that works within the language and that requires compromises on different features or syntax. Knowing the options is a hard problem in itself, understanding the compromises even harder and getting to a good solution much harder. And the good solution will probably be worse than the equivalent idiomatic C++ code.
If you program in C++, program C++. Trying to code python through a C++ compiler will probably give you the pain of C++ and the performance of python.

It doesn't deduce it because you never specified that Callable is a template. You make Callable a template template parameter and it should deduce its type for you.
template<template <typename T> typename Callable, typename Container>
auto map(const Callable<T>& function, Container&& iter)
-> MapObject<Callable<T>, Container>
{
return { function, std::forward<Container>(iter) };
}
You might get bitten though as you can't take the address of a template still to be instantiated. Not sure why you need the address-of though...

Related

overloading over function types with templates

There is a common abstraction for both containers and functions. I learned it in Haskell, and I'm trying to implement it in C++.
Most C++ programmers are familiar with std::transform, roughly speaking given a function from type A to B, you can convert a container of type A to a container of type B.
You can transform functions in a similar way, given a function foo from A to B, you can convert a function bar taking Z to A to a function foo . bar taking Z to B. The implementation is simple, it's just composition.
I wanted to define a function fmap, on containers and functions, to reflect this abstraction for generic programming.
The container was easy (I know this isn't fully general)
template <typename A, typename Func>
auto fmap(Func f, vector<A> in) {
vector<decltype(f(in[0]))> out_terms{};
for(auto vec : in)
out_terms.push_back(f(vec));
return out_terms;
}
However, the analogous function for functions makes me much more nervous.
template <typename FuncT, typename Func>
auto fmap(FuncT f, Func in) {
return [f, in](auto x){
return f(in(x));
};
}
Although the template won't specialize for anything except callable things, I'm worried this will confuse overload resolution. I would like to introduce type constraints on the template parameters to restrict their resolution to function types to keep the name space clean. And I was going to ask how to do that.
This abstraction is extremely general, there are corresponding fmaps for pointers to values, which I suspect might conflict as well.
So I think my question is, can I have two different template implementations with the same template level signature? I'm almost certain the answer is no but maybe something similar can be faked. And if not, what tools are available today to distinguish between the overloads? Especially for function types.
This seems, to me, to be a textbook case for concepts, though I'm not sure.
Edit: Boost would be acceptable to use, and SFINAE in particular. I'm trying to find a solution that would be familiar to most programmers, and as convenient, and canonical as possible. I could rename fmap to compose, but then the programmer would have to know to pass compose to a template function accepting fmap. That would be unfortunate, because fmap is semantically unique.
Edit 2: A trivial example of how this is used.
template <typename T>
auto double_everything(T in){
auto doublef = [](auto x){return 2*x;};
return fmap(doublef, in);
}
It generalizes maps over containers to maps over "container like" things. So double_everything(vector<int> {1, 2, 3}) returns a vector with its elements doubled. But double_everything([](int x){ return x + 1; }) returns a function whose outputs are twice the outputs of the increment function. Which is like doubling a kind of list. The abstraction has some nice properties, I'm not just making it up. At any rate, renaming the function fmap to compose doesn't answer the question.
Edit 3:
fmap for a template C takes functions from A to B to functions from C<A> to C<B> and satisfies fmap( compose(f, g) , c ) = fmap( f, fmap( g, c )). This is a nice structure preserving property.
Functions which do this for ranges already exist by different names. But ranges aren't the only templates on types. Here is fmap for std::optional:
template<typename T, typename Func>
auto fmap(Func f, optional<T> o) -> optional<f(*o)>{
if(o)
return f(*o);
else
{};
}
This implementation doesn't involve any range concepts at all, like thefmap for functions presented earlier. But it satisfies the semantic requirements for fmap.
I'm trying to define fmap for different overloads in the same way I would define a new operator * for a custom matrix type. So I would happily define fmap in terms of boost::transform_iterator. Then these algorithms would work with a function generic in terms of fmap.
Here is an example of such a function:
template <
template<typename, typename> class Cont,
typename Fmappable,
typename Alloc,
typename Func>
auto map_one_deep(Func f, Cont<Fmappable, Alloc> c){
auto g = [f](Fmappable x){ return fmap(f, x); };
return fmap(g, c);
}
now if we write
auto lists = vector<vector<int> > { {1, 2, 3}, {4, 5, 6} };
auto lists_squared = map_one_deep( [](int x){return x*x;} , lists);
lists_squared printed gives
1 4 9
16 25 36
If we instead had a vector of optionals, the optionals would be squared provided they contained elements.
I'm trying to understand how one should work with higher order functions in c++.
You can fake it with SFINAE, but you shouldn't. It's a matter of style and idiom.
Haskell is all about type classes, with a programmer expecting to have to spangle each type with all the clubs it belongs to. C++, in contrast, wants to be more implicit in specifying a type's capabilities. You've shown "vector" and "arbitrary callable" there, but why just vector? Why not an arbitrary container type? And this arbitrary container type I just wrote has an operator(), because reasons. So which one should it choose?
Bottom line, while you can use SFINAE tricks to resolve technical ambiguities, you shouldn't use them to resolve essential ambiguities. Just use two different names.
Here's the simplest compromise I found
template <typename FuncT, typename O, typename T>
auto fmap(FuncT f, function<O(T)> in){
return [f, in](T x){
return f(in(x));
};
}
Unfortunately this requires that function<Output(Input)> decorate the call site, and it litters indirections. I'm pretty sure this is the best one can do if constraining fmap is required.
Edit: You can do better. The link gives a way to restrict to callables, that also in-lines.
The function could be written like this:
template <typename FuncT, typename T>
auto fmap(FuncT f, tagged_lambda<T> in){
return tag_lambda([f, in](T x){
return f(in(x));
});
}
You could choose the version you want at the call site, by calling
fmap(g, tag_lambda({}(int x){return x + 1;}) );
or
fmap(g, function<int(int)>({}(int x){return x + 1;}) );
Given how templates work, I'm pretty sure tagging the function is required.
Here is a blog post which also talks about the issue, and discusses other options.
http://yapb-soc.blogspot.com/2012/10/fmap-in-c.html.

C++11 variadic std::function parameter

A function named test takes std::function<> as its parameter.
template<typename R, typename ...A>
void test(std::function<R(A...)> f)
{
// ...
}
But, if I do the following:
void foo(int n) { /* ... */ }
// ...
test(foo);
Compiler(gcc 4.6.1) says no matching function for call to test(void (&)(int)).
To make the last line test(foo) compiles and works properly, how can I modify the test() function? In test() function, I need f with type of std::function<>.
I mean, is there any template tricks to let compiler determine the signature of function(foo in example), and convert it to std::function<void(int)> automatically?
EDIT
I want to make this work for lambdas (both stateful and stateless) as well.
It looks like you want to use overloading
template<typename R, typename ...A>
void test(R f(A...))
{
test(std::function<R(A...)>(f));
}
This simple implementation will accept most if not all the functions you will try to pass. Exotic functions will be rejected (like void(int...)). More work will give you more genericity.
std::function implements the Callable interface, i.e. it looks like a function, but that doesn't mean you should require callable objects to be std::functions.
template< typename F > // accept any type
void test(F const &f) {
typedef std::result_of< F( args ) >::type R; // inspect with traits queries
}
Duck typing is the best policy in template metaprogramming. When accepting a template argument, be unspecific and just let the client implement the interface.
If you really need a std::function for example to re-target the variable or something crazy like that, and you know the input is a raw function pointer, you can decompose a raw function pointer type and reconsitute it into a std::function.
template< typename R, typename ... A >
void test( R (*f)( A ... ) ) {
std::function< R( A ... ) > internal( f );
}
Now the user can't pass a std::function because that has been encapsulated within the function. You could keep your existing code as another overload and just delegate to that, but be careful to keep interfaces simple.
As for stateful lambdas, I don't know how to handle that case. They don't decompose to function pointers and as far as I know the argument types cannot be queried or deduced. This information is necessary to instantiate std::function, for better or worse.
This is an old one, and I can't seem to find much on the same topic, so I thought I would go ahead and put in a note.
Compiled on GCC 4.8.2, the following works:
template<typename R, typename... A>
R test(const std::function<R(A...)>& func)
{
// ...
}
However, you can't just call it by passing in your pointers, lambdas, etc. However, the following 2 examples both work with it:
test(std::function<void(int, float, std::string)>(
[](int i, float f, std::string s)
{
std::cout << i << " " << f << " " << s << std::endl;
}));
Also:
void test2(int i, float f, std::string s)
{
std::cout << i << " " << f << " " << s << std::endl;
}
// In a function somewhere:
test(std::function<void(int, float, std::string)>(&test2));
The downside of these should stand out pretty obviously: you have to explicitly declare the std::function for them, which might look a little bit ugly.
That said, though, I threw that together with a tuple that gets expanded to call the incoming function, and it works, just requiring a little bit more of an explicitly saying what you're doing calling the test function.
Example code including the tuple thing, if you want to play with it: http://ideone.com/33mqZA
It's usually ill-advised to accept std::function by value unless you are at 'binary delimitation' (e.g. dynamic library, 'opaque' API) since as you've just witnessed they play havoc with overloading. When a function does in fact take an std::function by value then it's often the burden of the caller to construct the object to avoid the overloading problems (if the function is overloaded at all).
Since however you've written a template, it's likely the case that you're not using std::function (as a parameter type) for the benefits of type-erasure. If what you want to do is inspecting arbitrary functors then you need some traits for that. E.g. Boost.FunctionTypes has traits such as result_type and parameter_types. A minimal, functional example:
#include <functional>
#include <boost/function_types/result_type.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/function_type.hpp>
template<typename Functor>
void test(Functor functor) // accept arbitrary functor!
{
namespace ft = boost::function_types;
typedef typename ft::result_type<Functor>::type result_type;
typedef ft::parameter_types<Functor> parameter_types;
typedef typename boost::mpl::push_front<
parameter_types
, result_type
>::type sequence_type;
// sequence_type is now a Boost.MPL sequence in the style of
// mpl::vector<int, double, long> if the signature of the
// analyzed functor were int(double, long)
// We now build a function type out of the MPL sequence
typedef typename ft::function_type<sequence_type>::type function_type;
std::function<function_type> function = std::move(functor);
}
As a final note, I do not recommend introspecting functors (i.e. prodding for their result type and argument types) in the general case as that simply don't work for polymorphic functors. Consider several overloaded operator(): then there is no 'canonical' result type or argument types. With C++11 it's better to 'eagerly' accept any kind of functor, or constrain them using techniques like SFINAE or static_assert depending on the needs, and later on (when parameters are available) to use std::result_of to inspect the result type for a given set of arguments. A case where constraining up front is desirable is when the aim is to store functors into e.g. a container of std::function<Sig>.
To get a taste of what I mean by the previous paragraph it's enough to test the above snippet with polymorphic functors.

template for a function

This question was asked to me in an interview:
Lets say you have a function which can take any kind of arguments and any number of arguments.
How would you write a template function for the same?
I do not know the exact answer. could anybody suggest?
They checked your awareness of the upcoming C++ standard. The new feature is called "Variadic templates" and looks like this:
template<typename... Args> void f( const Args&... args )
{
// do something
}
For a more complicated examples see, e.g. this tutorial.
In C++03, for any number of argument in function template is not possible. However, for any type of argument you can write:
template<typename T, typename U>
void f( const T & t, const U &u )
{
//...
}
I agree that they were most probably looking for variadic templates, but for the sake of it, different approaches that can be taken in C++03:
Using a variant type
Use a container of a variant type. In this case boost::variant will not work, as it limits the number of types, but you can use boost::any:
void foo( std::vector< boost::any > args );
Compared to variadic templates, user code will be much more cumbersome, as instead of writting foo( a, b, c, d ), they will have to manually create the vector upfront. The syntax could be simplified by means of variadic macros (if the compiler supports them) and or helper templated functions to adapt the syntax, but this can quite easily become a mess.
The C way (non-template):
Use the ellipsis notation to write a function that takes an unknown number of arguments (and types):
void foo( type x, ... )
This approach has many shortcommings. The first one is that it is not typesafe, the compiler will not be able to detect that the arguments are the correct number or types, and it is undefined behavior if any of the arguments is a non-POD type, which limits usability from any type to POD types, which might or not be a limiting factor (you can always pass in a pointer to your non-POD object). Overall this is more complex to handle, and much more error prone so it should be avoided.
Not answering the question at all
In very few situations a single function should be able to take an unknown number of arguments of unknown types. Logging and i/o can require this, printf being such example. But that can be handled in C++ by means of operator overloading (in particular operator<<) and chaining. In a comment bind has been suggested, so yes, perfect forwarding in generic code is one such case, bind, std::thread...
It think this to be a good answer for an interview, as you can then discuss what the actual need for the function is, and whether there is any better alternative. It can be argued that if at the end you do need a container of a variant type, you can abuse operator overloading to simplify the syntax. Examples of this would be the boost::assign library, and in those lines you can create a helper argument builder as in:
class args {
public:
args() {}
operator std::vector<boost::any>&() {
return v;
}
template <typename T>
args& operator,( T x ) {
boost::any a = x;
v.push_back( a );
return *this;
}
private:
std::vector<boost::any> v;
};
// usage:
void foo( std::vector<boost::any> a ) {
std::cout << "Received " << a.size() << " arguments" << std::endl;
}
int main() {
foo(( args(), 1, 5.0, "a string", std::vector<int>(5,10) ));
}
Variadic templates
And of course, the best option that is a c++0x compiler that handles variadic templates, that requires no extra boiler plate code, and will make it much simpler to write both user code (directly as a regular function call) and the implementation of the function, whatever it is. As a motivating example, building a vector<boost::any> with variadic args:
typedef std::vector<boost::any> anyvector_t
// Stop condition, adding nothing at the end
void build_vector_impl( anyvector_t& ) {}
// Intermediate step, add a new argument to the vector and recurse:
template <typename Head, typename... Tail>
void build_vector_impl( anyvector_t& v, Head head, Tail... tail ) {
v.push_back( boost::any(head) );
build_vector_impl( v, tail... );
}
// Syntactic sugar: make it return the vector:
template <typename... Args>
anyvector_t build_vector( Args... args ) {
anyvector_t res;
build_vector_impl( res, args... );
return res;
}
// Test:
int main() {
std::cout << "Number of args: "
<< build_vector( 1, 5, "Hi", std::vector<int>( 5, 10 ) ).size()
<< std::endl;
}
That is not about templates. It's about variable arguments.
http://www.eskimo.com/~scs/cclass/int/sx11b.html

Lambda expressions: why no argument type inference? [duplicate]

I've been reviewing the draft version of the C++11 standard. Specifically the section on lambdas, and I am confused as to the reasoning for not introducing polymorphic lambdas.
For example, amongst the 100001 ways polymorphic lambdas could be used, I had hoped we could use code such as the following:
template<typename Container>
void foo(Container c)
{
for_each(c.begin(), c.end(), [](T& t) { ++t; });
}
What were the reasons:
Was it that the committee ran out of time?
That polymorphic lambdas are too hard to implement?
Or perhaps that they are seen as not being needed by the PTB?
Note: Please remember the example above is not the only one, and it is only provided as a guide to the types of code. Answers that solely concentrate on providing a workaround for the above piece of code will not be considered as valid!
Related sources:
Lambda expressions and closures for C++ (document number N1968=06-0038)
Can lambda functions be templated?
The reason we don't have polymorphic lambdas is explained pretty well in this posting.
It has to do with the concepts feature that was pulled from C++11: essentially, polymorphic lambdas are ordinary, unconstrained function templates and we didn't know how to typecheck a concept-constrained template that used an unconstrained template. However, solving that problem turns out to be easy as shown here(dead link), so I don't think there's any obstacle remaining.
The link to cpp-next is dead; the relevant info can be found here
Since the argument, c, meets the STL requirements for a container, you should be able to use something like
template<typename Container>
void foo(Container c)
{
for_each(c.begin(), c.end(),[](typename Container::reference t) { ++t; });
}
I'll also showcase John Purdy's comment above, which is another way to get the typename you want in this lambda:
template<typename Container>
void foo(Container c)
{
for_each(c.begin(),c.end(),[](decltype(*c.begin()) t) { ++t; });
}
(Yes, Dominar, I know you don't like this answer, because it doesn't answer your question, but I'm willing to bet that the next person who comes along asking this question is going to be looking for a way to make their code work, so it does make sense to have some techniques around where the question is relevant.)
It's probably because there already is a syntax for doing that, and the purpose of lambdas is to introduce a much simpler syntax that covers most cases. When you try to cover all cases (what if you wanted the auto-generated functor to inherit a particular base class?), you lose the comparative advantages (simplicity and terseness) of the lambda.
I really don't like the proposed syntax. Is T a keyword? Do all identifiers for which name lookup fails get turned automatically into template typename arguments? That prevents you from detecting misspellings, which IMO is a BAD idea:
for_each(c.begin(),c.end(),[](iterater& t) { ++t; });
// programmer misspelled "iterator" and now has a polymorphic lambda, oops
It also introduces action-at-a-distance behavior, if the named type get introduced in some header file somewhere, the meaning changes suddenly. Also really BAD.
Well, since it's supposed to create a template, we could borrow the existing syntax:
for_each(c.begin(),c.end(),[]template<typename T>(T& t) { ++t; });
This is unambiguous and now allows non-type template arguments (useful for accepting arrays by reference), but is really unwieldy. At this point you're better off writing out the functor by hand, it'll be much easier to understand.
However, I think a simple syntax is possible using the auto keyword:
for_each(c.begin(),c.end(),[](auto& t) { ++t; });
This next section incorrectly assumes that the template parameter appears on the functor type rather than its operator()():
But now you have a problem that for_each infers a typename template argument, not a template template argument. Type inference isn't possible in that context.
In the current proposal, lambdas have type, even if it's an unmentionable (other than decltype) type. You'd have to lose that feature in order to accommodate inference at the call-site.
Example showing that the issue is NOT a shortcoming of lambdas, it's simply a non-deducible context:
#include <vector>
#include <algorithm>
#include <iterator>
int main(void)
{
using namespace std;
vector<int> a(10);
vector<int> b(10);
vector<int> results;
transform(a.begin(), a.end(), b.begin(), back_inserter(results), min<int>);
}
The template type parameter to std::min must be explicitly specified. Lambdas are no different from using existing functors in this regard.
EDIT: Ok, now that I realize we aren't suggesting that the lambda generate a template functor type, but a single non-template functor type which implements a templated function application operator (operator()()), I agree that the compiler should be able to generate such a thing. I propose that using the auto keyword here would be a good simple syntax for requesting that.
However, I'm not really happy with auto either. What about lambdas with multiple parameters:
[](auto& x, auto& y){ return x + y; }
//becomes
template<typename T1, typename T2>
auto operator()(T1& x, T2& y) -> decltype(x + y) { return x + y; }
Ok, that works well enough, but what if we wanted two parameters but only one type argument:
[](auto& x, decltype(x)& y){ return x + y; }
//becomes
template<typename T1>
auto operator()(T1& x, T1& y) -> decltype(x + y) { return x + y; }
Seems ok, but I find the syntax misleading. The syntax suggests that the type parameter is inferred from the first actual parameter, and the second parameter is coerced to the same type, but actually both actual parameters are considered equal during type inference.
Perhaps it's best that this case be limited to one lambda parameter per type argument, and if you want something more constrained, write the functor yourself. This seems to me to be a good compromise between flexibility and power vs keeping the syntax simple.
Well, now that you've linked n1968, the answer to your question is apparent. It's found in section 5.1 of the proposal.
The following (your comment to my other answer above) works:
#include <algorithm>
#include <vector>
struct foo
{
template<typename T>
void operator()(T& t)
{
++t;
}
};
int main()
{
std::vector<int> v;
std::for_each(v.begin (),v.end(),foo());
return 0;
}
But the following does not:
#include <algorithm>
#include <vector>
template<typename T>
struct foo
{
void operator()(T& t)
{
++t;
}
};
int main()
{
std::vector<int> v;
std::for_each(v.begin (),v.end(),foo()); // <-- the syntax for foo here
// is kinda fictitious
return 0;
}
Probably the C++ committee saw lambdas as being more similar to the second example than the first. (Though I haven't figured out clever way to define a lambda in which this would make a difference. Anyone got any crazy ideas?)

C++11 and the lack of polymorphic lambdas - why?

I've been reviewing the draft version of the C++11 standard. Specifically the section on lambdas, and I am confused as to the reasoning for not introducing polymorphic lambdas.
For example, amongst the 100001 ways polymorphic lambdas could be used, I had hoped we could use code such as the following:
template<typename Container>
void foo(Container c)
{
for_each(c.begin(), c.end(), [](T& t) { ++t; });
}
What were the reasons:
Was it that the committee ran out of time?
That polymorphic lambdas are too hard to implement?
Or perhaps that they are seen as not being needed by the PTB?
Note: Please remember the example above is not the only one, and it is only provided as a guide to the types of code. Answers that solely concentrate on providing a workaround for the above piece of code will not be considered as valid!
Related sources:
Lambda expressions and closures for C++ (document number N1968=06-0038)
Can lambda functions be templated?
The reason we don't have polymorphic lambdas is explained pretty well in this posting.
It has to do with the concepts feature that was pulled from C++11: essentially, polymorphic lambdas are ordinary, unconstrained function templates and we didn't know how to typecheck a concept-constrained template that used an unconstrained template. However, solving that problem turns out to be easy as shown here(dead link), so I don't think there's any obstacle remaining.
The link to cpp-next is dead; the relevant info can be found here
Since the argument, c, meets the STL requirements for a container, you should be able to use something like
template<typename Container>
void foo(Container c)
{
for_each(c.begin(), c.end(),[](typename Container::reference t) { ++t; });
}
I'll also showcase John Purdy's comment above, which is another way to get the typename you want in this lambda:
template<typename Container>
void foo(Container c)
{
for_each(c.begin(),c.end(),[](decltype(*c.begin()) t) { ++t; });
}
(Yes, Dominar, I know you don't like this answer, because it doesn't answer your question, but I'm willing to bet that the next person who comes along asking this question is going to be looking for a way to make their code work, so it does make sense to have some techniques around where the question is relevant.)
It's probably because there already is a syntax for doing that, and the purpose of lambdas is to introduce a much simpler syntax that covers most cases. When you try to cover all cases (what if you wanted the auto-generated functor to inherit a particular base class?), you lose the comparative advantages (simplicity and terseness) of the lambda.
I really don't like the proposed syntax. Is T a keyword? Do all identifiers for which name lookup fails get turned automatically into template typename arguments? That prevents you from detecting misspellings, which IMO is a BAD idea:
for_each(c.begin(),c.end(),[](iterater& t) { ++t; });
// programmer misspelled "iterator" and now has a polymorphic lambda, oops
It also introduces action-at-a-distance behavior, if the named type get introduced in some header file somewhere, the meaning changes suddenly. Also really BAD.
Well, since it's supposed to create a template, we could borrow the existing syntax:
for_each(c.begin(),c.end(),[]template<typename T>(T& t) { ++t; });
This is unambiguous and now allows non-type template arguments (useful for accepting arrays by reference), but is really unwieldy. At this point you're better off writing out the functor by hand, it'll be much easier to understand.
However, I think a simple syntax is possible using the auto keyword:
for_each(c.begin(),c.end(),[](auto& t) { ++t; });
This next section incorrectly assumes that the template parameter appears on the functor type rather than its operator()():
But now you have a problem that for_each infers a typename template argument, not a template template argument. Type inference isn't possible in that context.
In the current proposal, lambdas have type, even if it's an unmentionable (other than decltype) type. You'd have to lose that feature in order to accommodate inference at the call-site.
Example showing that the issue is NOT a shortcoming of lambdas, it's simply a non-deducible context:
#include <vector>
#include <algorithm>
#include <iterator>
int main(void)
{
using namespace std;
vector<int> a(10);
vector<int> b(10);
vector<int> results;
transform(a.begin(), a.end(), b.begin(), back_inserter(results), min<int>);
}
The template type parameter to std::min must be explicitly specified. Lambdas are no different from using existing functors in this regard.
EDIT: Ok, now that I realize we aren't suggesting that the lambda generate a template functor type, but a single non-template functor type which implements a templated function application operator (operator()()), I agree that the compiler should be able to generate such a thing. I propose that using the auto keyword here would be a good simple syntax for requesting that.
However, I'm not really happy with auto either. What about lambdas with multiple parameters:
[](auto& x, auto& y){ return x + y; }
//becomes
template<typename T1, typename T2>
auto operator()(T1& x, T2& y) -> decltype(x + y) { return x + y; }
Ok, that works well enough, but what if we wanted two parameters but only one type argument:
[](auto& x, decltype(x)& y){ return x + y; }
//becomes
template<typename T1>
auto operator()(T1& x, T1& y) -> decltype(x + y) { return x + y; }
Seems ok, but I find the syntax misleading. The syntax suggests that the type parameter is inferred from the first actual parameter, and the second parameter is coerced to the same type, but actually both actual parameters are considered equal during type inference.
Perhaps it's best that this case be limited to one lambda parameter per type argument, and if you want something more constrained, write the functor yourself. This seems to me to be a good compromise between flexibility and power vs keeping the syntax simple.
Well, now that you've linked n1968, the answer to your question is apparent. It's found in section 5.1 of the proposal.
The following (your comment to my other answer above) works:
#include <algorithm>
#include <vector>
struct foo
{
template<typename T>
void operator()(T& t)
{
++t;
}
};
int main()
{
std::vector<int> v;
std::for_each(v.begin (),v.end(),foo());
return 0;
}
But the following does not:
#include <algorithm>
#include <vector>
template<typename T>
struct foo
{
void operator()(T& t)
{
++t;
}
};
int main()
{
std::vector<int> v;
std::for_each(v.begin (),v.end(),foo()); // <-- the syntax for foo here
// is kinda fictitious
return 0;
}
Probably the C++ committee saw lambdas as being more similar to the second example than the first. (Though I haven't figured out clever way to define a lambda in which this would make a difference. Anyone got any crazy ideas?)