je l'extrait suivant d'un exemple de code:C++: déduction argument du modèle lors du passage des fonctions de modèle comme argument à d'autres fonctions de modèle
L'idée est qu'il ya une classe de conteneur, appelé ici Box
, et que nous pourrions vouloir pour créer de nouvelles versions de ce conteneur par mapping une fonction sur son contenu actuel.
#include <iostream>
#include <tuple>
template <typename TContent>
class Box
{
TContent d_content;
public:
Box(TContent content)
:
d_content(content)
{}
TContent content() const
{
return d_content;
}
template <typename Function>
auto transform(Function fun) -> decltype(Box{fun(d_content)})
{
return Box{fun(d_content)};
};
};
template <typename TElem>
std::tuple<TElem, TElem> toTuple(TElem thing)
{
std::cout << "Transforming " << thing << "to tuple.\n";
return std::make_tuple(thing, thing);
}
int main() {
std::cout << "Hello World!\n";
Box<int> mybox{10};
Box<int> box2 = mybox.transform([](int content){ return content * 2;});
std::cout << "Transformed box: " << box2.content() << '\n';
Box<std::tuple<int, int>> box3 = mybox.transform(&toTuple); // <- Template argument deduction/substitution fails here!
std::cout << "Transformed box: " << std::get<0>(box3.content()) << '\n';
}
à la ligne 42, où box3 est créé, déduction argument template/substitution échoue:
main.cpp: In function 'int main()':
main.cpp:42:60: error: no matching function for call to 'Box<int>::transform(<unresolved overloaded function type>)'
Box<std::tuple<int, int>> box3 = mybox.transform(&toTuple);
^
main.cpp:22:8: note: candidate: template<class Function> decltype (Box<TContent>{fun(((Box<TContent>*)this)->Box<TContent>::d_content)}) Box<TContent>::transform(Function) [with Function = Function; TContent = int]
auto transform(Function fun) -> decltype(Box{fun(d_content)})
^~~~~~~~~
main.cpp:22:8: note: template argument deduction/substitution failed:
main.cpp:42:60: note: couldn't deduce template parameter 'Function'
Box<std::tuple<int, int>> box3 = mybox.transform(&toTuple);
^
exit status 1
Cela semble être le cas lors d'une tentative de passer d'une fonction de modèle (fonction template?) à une fonction qui attend elle-même un paramètre d'argument template. La seule façon d'éviter cela que j'ai trouvé jusqu'à présent est d'envelopper toutes les fonctions de modèle dans lambdas ou d'autres fonctions, non-modèle. Ceci est bien sûr sous-optimal, car il introduit beaucoup de passe-partout.
Pourquoi déduction argument modèle parviennent pas dans ce cas, et est-il un moyen de modifier le code de la classe Box
(et/ou sa fonction de membre transform
) pour faire en sorte que la déduction des arguments de modèle fait travail?
(Le code donné est 11 C++ comme repl.it ne supporte pas encore C++ 14. La principale différence en C++ 14 serait que le type de retour de fuite de transform
peut être omis. Le erreur, cependant, reste le même, je suis heureux avec des solutions (seulement) travaillent en C++ 14 ainsi)
Merci. Pour une raison quelconque, C++ 11 et C++ 14 compilent joyeusement le decltype mal formé. Quoi qu'il en soit, le changer en 'Box' le rendrait correct, non? –
Qqwy
Comme "toTuple" est un modèle de fonction, pas une fonction, vous ne pouvez pas le passer à un autre modèle de fonction car il n'a pas de type, il ne peut pas être déduit. " -> Y at-il des cas dans lesquels passer un modèle de fonction à un autre modèle de fonction où il peut être déduit? – Qqwy
@Qqwy Oui, vous pourriez. Et non, il n'y en a pas. – Barry