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 :

Déclaration de fonction amie


Sujet :

C++

  1. #1
    Membre régulier
    Homme Profil pro
    Ingénieur de recherche
    Inscrit en
    Octobre 2014
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Ingénieur de recherche
    Secteur : Service public

    Informations forums :
    Inscription : Octobre 2014
    Messages : 8
    Par défaut Déclaration de fonction amie
    Bonsoir,

    je cherche à déclarer une fonction amie mais j'obtiens l'erreur suivante avec g++:
    In file included from main.cpp:2:0:
    vector.hpp: In instantiation of ‘example::Vector<example::sequential>’:
    main.cpp:11:40: instantiated from here
    vector.hpp:23:27: erreur: template-id ‘dot<>’ for ‘PetscErrorCode example::dot(const example::Vector<example::sequential>&, const example::Vector<example::sequential>&, PetscScalar*)’ does not match any template declaration
    J'ai beau relire mon code, je ne vois pas où je commets une erreur.

    La fonction amie est déclarée dans une classe Vector
    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
    #ifndef VECTOR_HPP
    #define VECTOR_HPP
     
    #include <petscvec.h>
     
    // forward declaration of vector
    #include "vector_fwd.hpp"
     
     
     
    namespace example {
     
      // forward declaration of dot function
      template< template<class> class DistributionPolicy >
      PetscErrorCode dot(Vector<DistributionPolicy> const & x , Vector<DistributionPolicy> const & y , PetscScalar * val);
     
      template< template<class> class DistributionPolicy >
      class Vector : public DistributionPolicy<Vec>
      {
     
        friend PetscErrorCode dot<>(Vector<DistributionPolicy> const & x , Vector<DistributionPolicy> const & y , PetscScalar * val);
     
      private:
     
        Vec m_self;
     
      };
    }
     
    #include "vector_friend.hpp"
    et la fonction amie est définie par
    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
    #ifndef VECTOR_FRIEND_HPP
    #define VECTOR_FRIEND_HPP
     
     
    namespace example {
     
      template< template<class> class DistributionPolicy >
      inline PetscErrorCode dot(Vector<DistributionPolicy> const & x,
                                Vector<DistributionPolicy> const & y,
                                PetscScalar* val) {
        PetscErrorCode code = VecDot(x.m_self,y.m_self,val);
        CHKERRQ(code);
        return 0;
      }
     
    }
     
     
    #endif
    Est-ce que vous voyez où se situe le problème?

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Ta fonction dot est une fonction template. Tu dois donc prévenir le compilateur qu'il s'agit d'une fonction template, mais, pour ton malheur, cela ne fonctionnera qu'en C++11 et ultérieur.

    Si tu as la possibilité d'utiliser les fonctionnalités récemment ajoutées par la norme, tu devrais pouvoir définir une amitié envers une fonction template sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    template <typename T>
    void foo(T const &t ){
        std::cout<<t.member_<<"\n";
    }
    template <typename T>
    class MaClass{
       template<typename U>
       friend void foo(U const &);
    public:
       MaClass(T const & t):member_(t){}
    private:
            T member_;
    };
    qui serait utilisée sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int main()
    {
        MaClass<int> testint(3);
        foo(testint);
        MaClass<std::string> testString("salut");
        foo(testString);
        return 0;
    }
    Si tu n'a pas l'occasion de profiter des bienfaits de C++11 ou ultérieur, tu devras travailler à l'ancienne en créant par exemple un foncteur, sous une forme proche de
    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
     
    template <typename T>
    void foo(T const &t ){
        std::cout<<t<<"\n";
    }
    struct Functor{
    template <typename T>
       void operator()(T const & t){
            foo(t.member_);
       }
    };
    template <typename T>
    class MaClass{
       friend class Functor;
    public:
       MaClass(T const & t):member_(t){}
    private:
            T member_;
    };
    qui sera utilisée sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int main(){
        MaClass<int> testint(3);
        Functor()(testint);
        MaClass<std::string> testString("salut");
        Functor()(testString);
        /* OU  OU  OU */
       Functor f;
       f(testint);
       f(testString);
        return 0;
    }
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre régulier
    Homme Profil pro
    Ingénieur de recherche
    Inscrit en
    Octobre 2014
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Ingénieur de recherche
    Secteur : Service public

    Informations forums :
    Inscription : Octobre 2014
    Messages : 8
    Par défaut
    Bonjour koala01,

    je te remercie pour ta réponse.

    Je ne peux malheureusement pas utiliser la nouvelle norme.
    La solution par foncteur que tu proposes est intéressante mais je suis surpris qu'une solution plus directe ne soit pas possible.
    J'ai l'habitude de définir des fonctions template amies mais là il y a quelque chose qui bloque et je ne vois pas quoi.

    Pour illustrer mon propos, voici une relation d'amitié similaire qui compile et s'exécute sur ma machine, avec le même compilateur que précédemment.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include "foo.hpp"
    #include "nothing.hpp"
     
    int main()
    {
      example::Foo<nothing> foo;
      example::print(foo);
      return 0;
    }
    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
    #include "foo_fwd.hpp"
    #include "bar.hpp"
     
    namespace example
    {
     
      // forward declaration of print
      template< template<class> class Policy > 
      void print(Foo<Policy> const & foo);
     
      // definition of Foo
      template< template<class> class Policy >
      class Foo : public Policy<Bar>
      {
        friend void print<>(Foo<Policy> const & foo);
      };
     
    }
     
    #include "foo_friend.hpp"
     
    #endif
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #ifndef EXAMPLE_FOO_FRIEND_HPP
    #define EXAMPLE_FOO_FRIEND_HPP
     
    namespace example {
      // definition of print
      template< template<class> class Policy >
      void print(Foo<Policy> const & foo)
      { std::cout << "Hello!" << std::endl; }
    }
     
    #endif
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #ifndef EXAMPLE_NOTHING_HPP
    #define EXAMPLE_NOTHING_HPP
     
    #include "bar.hpp"
     
    template< class T >
    class nothing;
     
    template<>
    class nothing<Bar>
    {};
     
    #endif
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #ifndef EXAMPLE_BAR_HPP
    #define EXAMPLE_BAR_HPP
     
    class Bar
    {};
     
     
    #endif
    Merci beaucoup pour ton aide

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par défaut
    Hello tous les deux

    Il y a tout de même un détail dans le code de Cédric qui ne doit pas nous échapper : l'argument template de dot n'est pas un type mais un template, on est dans donc dans un cas tricky de template template. Or d'après ton message d'erreur, tu tentes de résoudre le template avec example::sequential comme argument. Est-ce example::sequential est bien un template et pas un type complètement résolu ? Dans l'exemple qui fonctionne, nothing est bien un template de la bonne forme donc ça fonctionne. Mais qu'en est-il de example::sequential ? Est-ce bien un template qui peut être résolu dans ce cas ? On n'a pas vu le code donc on ne peut pas savoir.

    Tu n'as pas affaire à de l'amitié templatée ici puisque ton template est résolu dans la déclaration d'amitié. Les techniques de Koala sont parfaitement valables mais ne s'appliquent pas pour ton problème il me semble.

  5. #5
    Membre régulier
    Homme Profil pro
    Ingénieur de recherche
    Inscrit en
    Octobre 2014
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Ingénieur de recherche
    Secteur : Service public

    Informations forums :
    Inscription : Octobre 2014
    Messages : 8
    Par défaut
    Bonjour jblecanard,

    merci pour ton intervention.

    Voici la classe sequential :
    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
    #ifndef SEQUENTIAL_HPP
    #define SEQUENTIAL_HPP
     
     
    namespace example {
     
      template< class T >
      struct sequential;
     
      template<>
      struct sequential<Vec>
      {
        static PetscErrorCode create(MPI_Comm comm,PetscInt n,Vec *v) { 
          PetscErrorCode code = VecCreateSeq(comm,n,v);
          CHKERRQ(code);
          return 0; 
        }
      };
    }
     
    #endif
    Il s'agit bien d'une classe template mais elle est totalement spécialisée pour Vec.

  6. #6
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par défaut
    Hello

    Je pense que le problème de vient pas de la déclaration d'amitié, car en reproduisant le code que tu nous montres de la manière la plus proche que je puisse, il n'y a aucun problème:

    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
    class Vec
    {};
     
    typedef int PetscErrorCode;
    typedef int PetscScalar;
    typedef int MPI_Comm;
    typedef int PetscInt;
     
    namespace example
    {
    template< template<class> class Policy > class Vector;
     
    template< template<class> class DistributionPolicy >
    PetscErrorCode dot(Vector<DistributionPolicy> const & x , Vector<DistributionPolicy> const & y , PetscScalar * val);
     
     
    template< template<class> class DistributionPolicy > class Vector : public DistributionPolicy<Vec>
    {
      friend PetscErrorCode dot<>(Vector<DistributionPolicy> const & x , Vector<DistributionPolicy> const & y , PetscScalar * val);
     private:
      Vec m_self;
     
    };
     
    template< template<class> class DistributionPolicy >
      inline PetscErrorCode dot(Vector<DistributionPolicy> const & x,
          Vector<DistributionPolicy> const & y,
          PetscScalar* val) {
        return 0;
      }
     
    template< class T > struct sequential;
     
    template<> struct sequential<Vec> {
      static PetscErrorCode create(MPI_Comm comm,PetscInt n,Vec *v) {
        return 0;
      }
    };
    }
     
    int main() {
      example::Vector<example::sequential> vec1;
      example::Vector<example::sequential> vec2;
      example::dot(vec1, vec2, 0);
      return 0;
    }
    Compile sans souci sous gcc 4.7 en mode C++03, et j'ai copié/collé depuis le post, pas reproduit.

  7. #7
    Membre régulier
    Homme Profil pro
    Ingénieur de recherche
    Inscrit en
    Octobre 2014
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Ingénieur de recherche
    Secteur : Service public

    Informations forums :
    Inscription : Octobre 2014
    Messages : 8
    Par défaut
    Bonsoir jblecanard,

    merci beaucoup d'avoir pris le temps de regarder.

    Je vais repartir de ton code qui compile également sur ma machine avec ma version de g++.
    En ajoutant petit à petit les briques me permettant d'évoluer vers mon code initial, je devrais probablement isoler le problème.

    Encore merci!

Discussions similaires

  1. fonctions amies
    Par Vips dans le forum C++
    Réponses: 10
    Dernier message: 24/03/2006, 04h41
  2. fonctions amies
    Par hamma2 dans le forum C++
    Réponses: 4
    Dernier message: 10/12/2005, 20h19
  3. [C++] Fonction amie vituelle dans une classe ?
    Par Bob.Killer dans le forum C++
    Réponses: 11
    Dernier message: 04/12/2005, 13h42
  4. Réponses: 6
    Dernier message: 20/11/2005, 02h53
  5. [JS] Problème déclaration de fonction
    Par glloq8 dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 23/09/2005, 10h22

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