xmllmx
xmllmx

Reputation: 42379

How to simplify the tedious parameter declaration of lambdas in C++0x?

The simplest code is the best asker:

#include <vector>
#include <algorithm>

using namespace std;

int main()
{
    vector<int> coll;
    for_each(coll.begin(), coll.end(), [](vector<int>::value_type n) -> void {});

    return 0;
}

Here, vector<int>::value_type n is tedious. I want to have an auto-like utility to deduce the right type of n automatically; just like the following:

for_each(coll.begin(), coll.end(), [](auto_type n) -> void {});

To be more greedy, I want auto_type to take an argument used to deduce the right type of n. The argument can be a (smart) pointer or reference to the container, or an iterator of the container.

Dear gurus, how to implement that?

Upvotes: 2

Views: 250

Answers (3)

JohannesD
JohannesD

Reputation: 14461

The early versions of the lambda proposal included provision for so-called polymorphic lambdas, with a simple syntax as follows:

auto print = [](x) { std::cout << x; };
print(42);
print("foo");

Unfortunately, there were technical issues in the proposal that the committee felt could not have been satisfactorily resolved given the already very tight schedule, so instead of standardizing a possibly broken feature, the introduction of polymorphic lambdas was deferred to a future standard revision.

Upvotes: 0

Puppy
Puppy

Reputation: 146968

You don't have to declare the void return in that function. You could use decltype, like, decltype(coll[0]).

std::for_each(coll.begin(), coll.end(), [](decltype(coll[0]) value) {
    std::cout << value;
});

Edit:

template<typename T> auto type(T&& t) -> decltype(*std::forward<T>(t).begin()) {
    return *t.begin();
}
std::for_each(coll.begin(), coll.end(), [](decltype(type(coll)) value) {
});

Upvotes: 2

Fred Nurk
Fred Nurk

Reputation: 14212

You should never write vector<int>::value_type instead of int, as you already know those are identical. A better example would help; I also would like simpler lambda parameters.

However, deducing parameter type depends on how the lambda is used, and that can only be known by knowing details of for_each. But function overload resolution depends on knowing the types of parameters, so parameter type cannot depend on how the function uses it, or you'd have a circular dependency.

In current C++, you avoid this circular dependency by decoupling the functor type from its parameter types:

struct AddExample {
  template<class T>
  T operator()(T a, T b) {
    return a + b;
  }
};

some_algo(begin, end, AddExample());

The equivalent could be done for the lambda syntax, at the cost of munging some semantics (e.g. implicit conversion to function pointers and std::function), but I don't see it happening for C++0x.

Upvotes: 1

Related Questions