2010-12-01 3 views
2

Le code le plus simple est le meilleur asker:Comment simplifier la déclaration fastidieuse des paramètres de lambdas en C++ 0x?

#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; 
} 

Ici, vector<int>::value_type n est fastidieux. Je veux avoir un utilitaire de type auto pour déduire le bon type de n automatiquement; tout comme les suivantes:

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

Pour être plus gourmand, je veux auto_type prendre un argument utilisé pour en déduire le type de n. L'argument peut être un pointeur (intelligent) ou une référence au conteneur, ou un itérateur du conteneur.

Chers gourous, comment mettre en œuvre cela?

Répondre

2

Vous n'avez pas besoin de déclarer le retour vide dans cette fonction. Vous pouvez utiliser decltype, comme, 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) { 
}); 
+1

Si le conteneur n'est pas de type vectoriel, alors decltype (coll [0]) n'est pas valide. Cette solution est moins générique. decltype (* coll.begin()) est trop moche. – xmllmx

+0

Parfois, nous avons seulement un itérateur, for_each (firs, last, [] (??? value) -> void {}); Que diriez-vous de auto_type dans un tel cas? – xmllmx

+0

@xmllmx: Vous pouvez écrire une aide triviale pour coll.begin(). Le problème avec l'écriture d'une sorte de auto_type dans ce cas est que vous ne pouvez pas modéliser un lambda ou son opérateur(), donc je doute fort que vous obtiendrez une réponse générique ici. – Puppy

1

Vous ne devriez jamais écrire vecteur < int> :: value_type au lieu de int, comme vous le savez ce sont identiques. Un meilleur exemple aiderait; Je voudrais aussi des paramètres lambda plus simples. Cependant, déduire le type de paramètre dépend de la façon dont le lambda est utilisé, et cela ne peut être connu qu'en connaissant les détails de for_each. Mais la résolution de surcharge de fonction dépend de la connaissance des types de paramètres, de sorte que le type de paramètre ne peut pas dépendre de la façon dont la fonction l'utilise, ou vous auriez une dépendance circulaire.

Dans ++ courant C, vous éviter cette dépendance circulaire en découplant le type foncteur de ses types de paramètres:

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

some_algo(begin, end, AddExample()); 

L'équivalent pourrait être fait pour la syntaxe lambda, au coût de munging une sémantique (par exemple implicite conversion aux pointeurs de fonction et std :: function), mais je ne vois pas cela se produire pour C++ 0x.

0

Les premières versions de la proposition lambda inclus disposition pour soi-disant lambdas polymorphes, avec une syntaxe simple comme suit:

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

Malheureusement, il y avait des problèmes techniques dans la proposition que le Comité a estimé ne pouvait pas avoir été résolus de manière satisfaisante étant donné le calendrier déjà très serré, ainsi, au lieu de normaliser une caractéristique éventuellement brisée, l'introduction de lambdas polymorphes a été reportée à une future révision standard.