32 votes

La lambda passée au modèle n'est pas définie

Je jouais aujourd'hui avec la déduction des arguments des modèles de classe de C++17. La première idée évidente qui m'est venue à l'esprit était de passer un callable comme paramètre de modèle. Un callable, c'est entre autres un lambda, pourquoi pas. Essayons cela.

template<typename F> class foo
{
F f;
public:
    foo(F in) : f(in) { f(); /* not very useful, admitted */ }
};

void bar() { puts("a"); }

int main()
{
    auto a = foo(bar);
    auto b = foo([](){ puts("b"); });

    return (void) a, (void) b, 0;
}

Voici ce que clang (5.0, r300688) a à dire à ce sujet :

warning : la fonction '<(lambda at [source location])>' a un lien interne mais n'est pas définie.

Le code se compile et "fonctionne bien", mais l'avertissement suggère que le compilateur n'est pas tout à fait satisfait.

Je suis prêt à accepter que le lambda a un lien interne (étant anonyme il n'est pas accessible ailleurs dans la même unité de traduction, donc bien sûr il est inaccessible dans une autre), mais qu'en est-il. I ne veulent pas y accéder à partir d'une autre unité de traduction.
La partie concernant l'absence de définition me fait rire, je ne saurais même pas comment écrire un lambda sans le définir.

En résumé : Que se passe-t-il ? Que penser de tout cela ? Je n'aime pas les avertissements, non seulement ils rendent le build moins joli, mais ils généralement signifie que quelque chose ne va pas et qu'un comportement indéfini risque de vous mordre bientôt. D'un autre côté, comment puis-je faire un lambda plus défini qu'elle ne l'est déjà en écrivant sa définition ?

1voto

Flaviu Points 340

Il me semble qu'il s'agit d'un problème de compilation. En utilisant le compilateur Clang de Visual Studio 2017, seule cette erreur est générée "cannot refer to class template 'foo' without a template argument list" pour l'instanciation de a et b dans la fonction main. Si le type de fonction est spécifié comme paramètre de template, il n'y a aucun avertissement et aucune erreur.

0voto

fish2000 Points 1523

Récemment, je suis tombé sur quelques avertissements absurdes qui ressemblaient, et sentaient, comme les vôtres. J'ai essayé un tas de corrections manuelles avec l'idée que je pourrais forcer la main de l'éditeur de liens (si vous voulez) - mais à la fin de la journée, j'ai réalisé que j'essayais de compiler du code C++14 avec un code de type -std=c++17 drapeau. Vous pouvez vérifier vos propres drapeaux de normes (et éventuellement vos drapeaux de normes correspondants). -stdlib=… également).

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