2017-04-02 1 views
3

Tiré de cppreference, pourquoi l'appel à std::apply(add_generic, ...) ne parvient pas à compiler? Y a-t-il un moyen de le réparer?Pourquoi std :: apply échoue avec une fonction générique?

#include <iostream> 
#include <tuple> 

int add(int first, int second) 
{ 
    return first + second;  
} 

template<typename T> 
T add_generic(T first, T second) 
{ 
    return first + second;  
} 

int main() 
{ 
    std::cout << std::apply(add, std::make_tuple(1,2)) << '\n'; 

    // template argument deduction/substitution fails 
    std::cout << std::apply(add_generic, std::make_tuple(2.0f,3.0f)) << '\n'; 
} 

Il fails avec l'erreur:

[x86-64 gcc 7 (snapshot)] error: no matching function for call to 'apply(, std::tuple)' [x86-64 gcc 7 (snapshot)] note: couldn't deduce template parameter '_Fn'

+0

Sans voir les erreurs éventuelles, je suppose qu'il est possible être en raison de ne pas être capable de déduire correctement le type d'argument 'T'? –

+0

Comment compilez-vous le code? 'std :: apply' nécessite' C++ 17', votre compilateur a-t-il le support 'C++ 17'? – Rogus

+3

'add_generic' n'est pas une fonction, c'est un template. Vous ne pouvez pas déduire un type de quelque chose qui n'a pas de type. – chris

Répondre

8

Ce n'est pas nouvelle en C++ 17. Juste à partir de la signature de std::apply, il n'est pas dit si vous voulez passer add_generic<int>, add_generic<float>, add_generic<std::string>, ou toute autre chose. Sachant que cela nécessite plus de contexte (en particulier: il faut savoir comment std::apply va l'invoquer), mais cette information n'est pas disponible sur le site d'appel et ne peut donc pas être utilisée pour la déduction des arguments de modèle.

Il est possible de travailler autour de ce en passant un objet et faisant qu'un objet capable d'appeler selon instanciation de add_generic est nécessaire:

std::cout << std::apply(
    [](auto first, auto second) { return add_generic(first, second); }, 
    std::make_tuple(2.0f,3.0f)) << '\n';