63 votes

C ++11 ne déduit pas le type lorsque std :: function ou les fonctions lambda sont impliqués

Quand j'définir cette fonction,

template<class A>
set<A> test(const set<A>& input) {
    return input;
}

Je peux l'appeler à l'aide de test(mySet) ailleurs dans le code, sans avoir à définir explicitement le type de modèle. Cependant, lorsque j'utilise la fonction suivante:

template<class A>
set<A> filter(const set<A>& input,function<bool(A)> compare) {
    set<A> ret;
    for(auto it = input.begin(); it != input.end(); it++) {
        if(compare(*it)) {
            ret.insert(*it);
        }
    }
    return ret;
}

Lorsque j'appelle cette fonction à l'aide d' filter(mySet,[](int i) { return i%2==0; }); J'obtiens l'erreur suivante:

error: no matching function for call to ‘filter(std::set<int>&, main()::<lambda(int)>)'

Cependant, toutes ces versions n' travail:

std::function<bool(int)> func = [](int i) { return i%2 ==0; };
set<int> myNewSet = filter(mySet,func);

set<int> myNewSet = filter<int>(mySet,[](int i) { return i%2==0; });

set<int> myNewSet = filter(mySet,function<bool(int)>([](int i){return i%2==0;}));

Pourquoi le c++11 est impossible de deviner le type de modèle quand j'ai mis la fonction lambda directement à l'intérieur de l'expression sans créer directement un std::function?

EDIT:

Par les conseils de Luc Danton dans les commentaires, ici, est une alternative à la fonction que j'avais précédemment qui n'a pas besoin de modèles pour être transmis de manière explicite.

template<class A,class CompareFunction>
set<A> filter(const set<A>& input,CompareFunction compare) {
    set<A> ret;
    for(auto it = input.begin(); it != input.end(); it++) {
        if(compare(*it)) {
            ret.insert(*it);
        }
    }
    return ret;
}

Cela peut être appelé par set<int> result = filter(myIntSet,[](int i) { i % 2 == 0; }); sans avoir besoin du modèle.

Le compilateur peut même deviner les types de retour, dans une certaine mesure, à l'aide de la nouvelle decltype mot-clé et à l'aide de la nouvelle fonction de type de retour de la syntaxe. Voici un exemple qui convertit un ensemble à une carte, à l'aide d'une fonction de filtrage et une fonction qui génère les clés sur la base des valeurs:

template<class Value,class CompareType,class IndexType>
auto filter(const set<Value>& input,CompareType compare,IndexType index) -> map<decltype(index(*(input.begin()))),Value> {
    map<decltype(index(*(input.begin()))),Value> ret;
    for(auto it = input.begin(); it != input.end(); it++) {
        if(compare(*it)) {
            ret[index(*it)] = *it;
        }
    }
    return ret;
}

Il peut aussi être appelé sans l'aide du modèle directement, comme

map<string,int> s = filter(myIntSet,[](int i) { return i%2==0; },[](int i) { return toString(i); });

68voto

La question est sur la nature des lambdas. Ils sont des objets de fonction avec un ensemble fixe de biens, conformément à la norme, mais ils sont pas une fonction. La norme détermine que les lambdas peuvent être convertis en std::function<> , avec exactement les types d'arguments et, si ils n'ont pas d'état, des pointeurs de fonction.

Mais cela ne signifie pas qu'un lambda est un std::function ni un pointeur de fonction. Ils sont des types uniques de mise en œuvre operator().

Type de déduction, d'autre part, ne déduire types exacts, avec pas de conversions (autres que const/volatils qualifications). Parce que le lambda n'est pas un std::function le compilateur ne peut pas déduire le type de l'appel: filter(mySet,[](int i) { return i%2==0; }); tout std::function<> de l'instanciation.

Comme d'autres exemples, dans le premier vous convertir le lambda pour le type de fonction, et de passer ensuite que. Le compilateur peut déduire le type là-bas, comme dans le troisième exemple où l' std::function est une rvalue (temporaire) d'un même type.

Si vous fournissez à l'instanciation de type int pour le modèle, second exemple, la déduction ne s'applique pas à le compilateur utilisera le type et ensuite convertir le lambda du type approprié.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X