IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

call of overloaded 'specifier’ is ambiguous


Sujet :

C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2013
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France, Essonne (Île de France)

    Informations forums :
    Inscription : Avril 2013
    Messages : 32
    Points : 18
    Points
    18
    Par défaut call of overloaded 'specifier’ is ambiguous
    Bonjour,

    Le code suivant me permet de récupérer des pointeurs de fonctions sur le stack lua pour les appeler ensuite. J'utilise enable_if pour différencier le cas où j'attends une fonction qui return void (pas de valeur à return ni à read) d'une fonction qui return quelque chose.
    Actuellement, quelque soit la std::function que je demande de lire sur le stack, je reçois :

    error: call of overloaded ‘_get(_id<std::function<int(int)> >, lua_State* const&, const int&)’ is ambiguous
    Une idée de la raison ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    template <typename Ret, typename... Args>
     typename std::enable_if<!std::is_void<Ret>::value, std::function<Ret(Args...)> >::type 
      _get(_id<std::function<Ret(Args...)> >, lua_State *l, const int index) 
    {
    	lua_pushvalue(l, index);
    	auto lambda = [l](Args... args) -> Ret {
    		//Get the reference
    		lua_rawgeti(l, LUA_REGISTRYINDEX, luaL_ref(l, LUA_REGISTRYINDEX));
    		State s(l);
    		//Push the arguments on the stack
    		s.push(args...);
    		constexpr int num_args = sizeof...(Args);
    		//Call the function
            lua_call(l, num_args, 1);
            Ret ret = s.read<Ret>(-1);
            lua_settop(l, 0);
            return ret;
    	};
        return lambda;
    }
     
    template <typename Ret, typename... Args>
     typename std::enable_if<std::is_void<Ret>::value, std::function<Ret(Args...)> >::type 
     _get(_id<std::function<Ret(Args...)> >, lua_State *l, const int index) 
    {
    	lua_pushvalue(l, index);
    	auto lambda = [l](Args... args) {
    		//Get the reference
    		lua_rawgeti(l, LUA_REGISTRYINDEX, luaL_ref(l, LUA_REGISTRYINDEX));
    		State s(l);
    		//Push the arguments on the stack
    		s.push(args...);
    		constexpr int num_args = sizeof...(Args);
    		//Call the function
            lua_call(l, num_args, 1);
            lua_settop(l, 0);
    	};
        return lambda;
    }
    Merci

  2. #2
    Candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2013
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2013
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Bonjour,

    Je comprends pas très bien ton typename à cet endroit du code.
    Mais si je me trompe pas, c'est tout simplement que tu définis deux fois la méthode _get avec un prototype identique. Il prends ça comme une surcharge, mais il est incapable de savoir lequel appeler dans la pratique.

  3. #3
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Citation Envoyé par Yuri_Hyuga Voir le message
    Bonjour,

    Je comprends pas très bien ton typename à cet endroit du code.
    Mais si je me trompe pas, c'est tout simplement que tu définis deux fois la méthode _get avec un prototype identique. Il prends ça comme une surcharge, mais il est incapable de savoir lequel appeler dans la pratique.
    Le typename est nécessaire car tu peux imaginer avoir une spécialisation de std::enable_if qui à un membre type qui n'est pas un type...

    Le but de LiquidHuk est d'avoir une fonction qui prend une std::function et dont le code varie si la std::function retourne void ou pas.
    Pour cela il va falloir écrire deux fois la fonction, une qui est valide lorsque le type de retour de la std::function est void, une autre lorsque le type de retour de la std::function n'est pas void.
    En apparence, les deux fonctions auront le même prototype, mais ce n'est pas le cas.
    std::enable_if (et plus largement SFINAE) permet de faire cela.

    @LiquidHuk
    Voici un code qui fait à peu près ce que tu veux (?)
    Il faudra que tu l'améliore pour les vrais types de args_t et pour la conversion facile/automatique depuis des fonctions "classiques" vers std::function.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    // g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++11 -pedantic -fopenmp main.cpp -o main && ./main
    // g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++98 -pedantic -fopenmp main.cpp -o main && ./main
     
    #include <iostream>
    #include <string>
    #include <functional>
    #include <type_traits>
     
     
    template <class return_t, class... args_t>
    typename std::enable_if<std::is_void<return_t>::value, return_t>::type get(std::function<return_t (args_t ...)> const & fct, args_t ... args)
    {
    	fct(args...);
    }
     
    template <class return_t, class... args_t>
    typename std::enable_if<! std::is_void<return_t>::value, return_t>::type get(std::function<return_t (args_t ...)> const & fct, args_t ... args)
    {
    	return fct(args...);
    }
     
    int main()
    {
    	std::function<void (int const, int const, int const)> f = [](int const i, int const j, int const k)
    	{
    		std::cout << "f(" << i << ", " << j << ", " << k << ")" << std::endl;
    	};
     
    	std::function<double (std::string const /*&*/, double const)> g = [](std::string const /*&*/ s, double const d) -> double // const & à corriger
    	{
    		std::cout << "g(\"" << s << "\", " << d << ")" << std::endl;
    		return d * d;
    	};
     
    	get(f, 1, 2, 3);
    	std::cout << std::endl;
     
    	auto const r = get(g, std::string("test"), 3.14);
    	std::cout << "r = " << r << std::endl;
     
    	return 0;
    }
    L'affichage est celui attendu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    f(1, 2, 3)
     
    g("test", 3.14)
    r = 9.8596
    Edition : inversion des pseudos...

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2013
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France, Essonne (Île de France)

    Informations forums :
    Inscription : Avril 2013
    Messages : 32
    Points : 18
    Points
    18
    Par défaut
    En effet Ehonn, j'utilise les std::enable_if pour ça. Ta solution fonctionne, mais ne m'aide pas à comprendre pourquoi la mienne ne fonctionne pas.
    J'ai fais la même chose ou presque : J'utilise juste une dummy structure pour passer le type (id) car je ne passe pas directement la fonction en argument (et ses arguments), je la lis sur le stack lua avec les arguments qui vont avec.

  5. #5
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Je ne sais pas trop :s
    Il faudrait avoir un code minimal qui reproduit l'erreur.

  6. #6
    Membre éprouvé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2014
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2014
    Messages : 345
    Points : 1 211
    Points
    1 211
    Par défaut
    Salut,

    Est-tu sûr que le code fourni par Ehonn fait ce que tu veux ?
    La fonction _get que tu présentes dans le premier post renvoie une fonction, alors que celle de Ehonn exécute une fonction ...

    Au passage, Ehonn, pourquoi tous ces const ?

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2013
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France, Essonne (Île de France)

    Informations forums :
    Inscription : Avril 2013
    Messages : 32
    Points : 18
    Points
    18
    Par défaut
    J'ai seulement dit qu'elle fonctionnait (dans son cas). J'ai également précisé que ça ne m'aidait pas à résoudre le problème.
    J'ai sorti les fonctions de leur contexte pour tester et ça fonctionne bien. Je dois donc chercher le problème ailleurs.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
     
    //g++ -Wall -Wextra -pedantic-errors -std=gnu++11 -c test.cpp -o test
    #include <functional>
     
    template <typename T> struct _id {};
     
    template <typename Ret, typename... Args>
    typename std::enable_if<std::is_void<Ret>::value, std::function<Ret(Args...)> >::type
    _get(_id<std::function<Ret(Args...)> >, const int )
    {
    	auto lambda = [](Args... ) {
    	};
        return lambda;
    }
     
    template <typename Ret, typename... Args>
    typename std::enable_if<!std::is_void<Ret>::value, std::function<Ret(Args...)> >::type
    _get(_id<std::function<Ret(Args...)> >, const int )
    {
    	auto lambda = [](Args... ) -> Ret {
    		Ret ret(0);
    		return ret;
    	};
        return lambda;
    }
     
    bool _get(_id<bool>, const int ) {
        return true;
    }
    int _get(_id<int>, const int ) {
        return 10;
    }
     
     unsigned int _get(_id<unsigned int>, const int ) {
        return 10;
    }
     
     std::string _get(_id<std::string>, const int ) {
        return "a";
    }
     
    int main(int, char **) {
    	_id<std::function<void(int)> > id;
    	_id<std::function<int(int)> > id2;
    	auto f = _get(id, 0);
    	auto f2 = _get(id2, 0);
     
    	f(10);
     
        return 0;
     
    }
    EDIT : Bon, c'était une erreur débile que j'aurais pu trouver seul si j'avais pris la bonne habitude d'isoler le code pour chercher l'erreur. J'avais juste écris la ignature de la fonction plus haut dans le fichier et je ne l'avais pas mis à jour après duplication & std::enable_if...
    Merci beaucoup pour votre aide qui m'a mené à la solution !

  8. #8
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Citation Envoyé par the Hound Voir le message
    Au passage, Ehonn, pourquoi tous ces const ?
    Car j'ai pas besoin de modifier les paramètres.

    Citation Envoyé par LiquidHuk Voir le message
    EDIT : Bon, c'était une erreur débile que j'aurais pu trouver seul si j'avais pris la bonne habitude d'isoler le code pour chercher l'erreur. J'avais juste écris la ignature de la fonction plus haut dans le fichier et je ne l'avais pas mis à jour après duplication & std::enable_if...
    Merci beaucoup pour votre aide qui m'a mené à la solution !
    Je me doutais bien que c'était un truc du genre ^^

  9. #9
    Membre éprouvé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2014
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2014
    Messages : 345
    Points : 1 211
    Points
    1 211
    Par défaut
    Citation Envoyé par Ehonn Voir le message
    Car j'ai pas besoin de modifier les paramètres.
    C'est donc uniquement une question sémantique/syntaxique ?
    Techniquement rajouter const à des paramètres non-référence (*, &, &&) ne sert à rien, mais on s'en fout, c'est pas le sujet

  10. #10
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Oui, ça évite d'écrire des bugs stupides.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. vba nom ambigu detecté dans un call
    Par cecile_64 dans le forum Excel
    Réponses: 2
    Dernier message: 16/08/2012, 11h17
  2. [POO] Héritage et "ambiguous call"
    Par coberle dans le forum C++
    Réponses: 4
    Dernier message: 18/11/2008, 18h46
  3. Réponses: 21
    Dernier message: 06/05/2007, 12h49
  4. Réponses: 2
    Dernier message: 15/11/2005, 11h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo