8
votes

C ++ 0x: Surcharge sur Lambda ARITY

J'essaie de créer une fonction qui peut être appelée avec une Lambda qui prend 0, 1 ou 2 arguments. Étant donné que j'ai besoin du code pour travailler à la fois sur G ++ 4.5 et VS2010 (qui ne prend pas en charge les modèles variadiques ou les conversions Lambda vers des pointeurs de fonction) La seule idée que j'ai proposée est de choisir la mise en œuvre à appeler en fonction de la monnaie. Ce qui est ci-dessous est mon non-marche devinez comment cela devrait regarder. Y a-t-il un moyen de corriger mon code ou y a-t-il un meilleur moyen de le faire en général? XXX


1 commentaires

Pouvez-vous montrer un exemple de code qui appellerait la fonction Lambda?


4 Réponses :


1
votes

Je pensais que ce qui suit fonctionnerait mais ça ne le fait pas, je le pose pour deux raisons.

  1. sauver les gens le temps s'ils avaient la même idée
  2. Si quelqu'un sait pourquoi cela ne fonctionne pas, je ne suis pas sûr à 100% que je comprends (bien que j'ai mes soupçons)

    code suit: xxx


1 commentaires

STD :: Fonction sait comment envelopper Lambdas, mais vous devez fournir directement la signature <...>. Par exemple: "Modèle Void FOO (Vector );", vous ne pouvez pas passer la liste des initialiseurs de FOO! Le compilateur sait quoi faire avec le vecteur :: vecteur (initialisizer_list ), mais il doit savoir t premier à l'obtenir aussi loin. Le compilateur ne peut pas partir de initialisizer_list , voir un vecteur , puis choisir par magiquement T = x afin que les choses correspondent à ce que les choses correspondent. C'est en arrière.



17
votes

Une fonction Lambda est un type de classe avec un seul appel d'appel de fonctions. Vous pouvez ainsi détecter l'arité de cet opérateur d'appel de la fonction en prenant son adresse et en utilisant la résolution de surcharge pour sélectionner la fonction à appeler:

#include <iostream>

template<typename F,typename R>
void do_stuff(F& f,R (F::*mf)() const)
{
    (f.*mf)();
}

template<typename F,typename R,typename A1>
void do_stuff(F& f,R (F::*mf)(A1) const)
{
    (f.*mf)(99);
}

template<typename F,typename R,typename A1,typename A2>
void do_stuff(F& f,R (F::*mf)(A1,A2) const)
{
    (f.*mf)(42,123);
}

template<typename F>
void do_stuff(F f)
{
    do_stuff(f,&F::operator());
}

int main()
{
    do_stuff([]{std::cout<<"no args"<<std::endl;});
    do_stuff([](int a1){std::cout<<"1 args="<<a1<<std::endl;});
    do_stuff([](int a1,int a2){std::cout<<"2 args="<<a1<<","<<a2<<std::endl;});
}


2 commentaires

Très cool, mais vous n'avez pas besoin d'appeler la fonction (car il vous suffit de contraindre les types de paramètres) et que vous souhaitez renvoyer le nombre de paramètres de do_stuff (qui peut être mieux nommé < Code> ARITY ).


Avec C ++ 11 et des modèles variadiques, nous pouvons faire mieux maintenant.



-1
votes

De cette façon fonctionne:

template<typename F>
auto call(F f) -> decltype(f(1))
{
    return f(1);
}

template<typename F>
auto call(F f, void * fake = 0) -> decltype(f(2,3))
{
    return f(2,3);
}

template<typename F>
auto call(F f, void * fake = 0, void * fake2 = 0) -> decltype(f(4,5,6))
{
    return f(4,5,6);
}

int main()
{
    auto x1 = call([](int a){ return a*10; });
    auto x2 = call([](int a, int b){ return a*b; });
    auto x3 = call([](int a, int b, int c){ return a*b*c; });
    // x1 == 1*10
    // x2 == 2*3
    // x3 == 4*5*6
}


0 commentaires

0
votes

Compiler des moyens de compilation d'obtention de l'arité d'une fonction ou d'un objet de fonction, y compris celui d'une Lambda: xxx


xxx

0 commentaires