2017-08-13 1 views
1

Récemment, j'ai travaillé dans la toile de JS pour faire des fractals dans deux et trois dimensions. En ce moment, je travaille sur le portage de mon projet en C++ via SDL et Eigen. Il est très important que je puisse composer des fonctions pour une utilisation ultérieure. Le code ci-dessous est ma première tentative de faire une usine de fonction composite:Erreur de lien sur le retour lambda de la fonction de deux lambdas

std::function< Eigen::Vector3f(Eigen::Vector3f) > compose3d(std::function< 
Eigen::Vector3f(Eigen::Vector3f) > a, std::function< 
Eigen::Vector3f(Eigen::Vector3f) > b){ 
    return [&](Eigen::Vector3f vec)->Eigen::Vector3f{ 
     return b(a(vec)); 
    }; 
} 

Actuellement, ce me donne une erreur de symbole en double pendant la liaison. Si ce code est supprimé, l'erreur disparaît. Je me suis assuré que cette fonction est à l'intérieur d'une section ifndef de mon en-tête. Je sais que ce n'est pas la meilleure pratique d'avoir des fonctions entièrement définies dans l'en-tête, mais j'aimerais que les choses fonctionnent avant de refactoriser.

Dans l'ensemble, je veux juste savoir si ce problème est une erreur dans l'écriture de la fonction si je devais chercher ailleurs dans mon code des définitions en double. Je suis conscient qu'il est préférable de créer des listes de pointeurs de fonction plutôt que de créer des listes de fonctions et je vais travailler sur l'implémentation après que cette erreur de l'éditeur de liens soit résolue.

Désolé si c'est affreux, je n'ai pas écrit C++ très longtemps et c'est ma première tentative de lambda.

Merci!

+3

Faire la fonction 'inline'? Par exemple. voir https://stackoverflow.com/questions/5971736/c-inline-function – stijn

+1

Cela n'a rien à voir avec lambdas. –

+0

Vous n'êtes pas censé définir des fonctions dans les en-têtes et cette erreur est pourquoi. Il ne s'agit pas de "meilleures pratiques". – melpomene

Répondre

0

Déclarez-le "en ligne". Sinon, tous les fichiers contenant le fichier d'en-tête créeront une fonction distincte avec cette signature.

0

Le problème de liaison est très probablement dû au fait que vous avez la définition de fonction dans un fichier d'en-tête qui est inclus dans plusieurs unités de compilation. Cela entraîne des erreurs de définition en double. Vous devez soit déplacer la déclaration vers une compilation unique (en ne laissant qu'une déclaration dans le fichier d'en-tête), soit créer la fonction static ou inline, ce qui permet de multiples définitions dans différentes unités de compilation.

Un problème beaucoup plus important est le fait que vous vous liez par référence aux arguments de la fonction, puis renvoyez le lambda avec les références liées. Ces références deviendront pendantes après le retour de la fonction, conduisant à un comportement indéfini lorsque vous essayez d'appeler le lambda retourné. C'est une erreur particulièrement délétère, car il est susceptible de fonctionner pour des exemples simples et de tester des programmes (avec tout ce qui est en ligne) et d'échouer pour des cas plus complexes.

Pour corriger cela, vous devez lier les arguments par valeur plutôt que par référence - utilisez [=] au lieu de [&].