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 :

std::enable_if, variadic template et constructeur


Sujet :

C++

Vue hybride

Message pr�c�dent Message pr�c�dent   Message suivant Message suivant
  1. #1
    Membre �clair�
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels
    Secteur : Sant�

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Par d�faut std::enable_if, variadic template et constructeur
    Bonjour tout le monde,

    J'ai une petite question dont je n'arrive pas � trouver de r�ponse sur le net: comment/peut-on utiliser std::enable_if avec les variadic templates pour activer ou non tel constructeur en fonction du nombre de param�tre?

    Voici un petit exemple:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template<size_t SIZE = 3>
    class Test
    {
       public:
         template<typename... Args>
         Test(typename<std::enable_if<sizeof...(Args) <= SIZE, Args...>::type args) // J'ai essayé différentes syntaxe mais ça ne semble pas fonctionner
         {
          // blabla
         }
    };
    A l'heure actuelle, pour avoir le comportement voulu, j'utilise static_assert:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template<size_t SIZE = 3>
    class Test
    {
       public:
         template<typename... Args>
         Test(Args... args)
         {
            static_assert(sizeof...(Args) <= SIZE, "Trop d'arguments");
         }
    };
    C'est plus une question pour satisfaire ma curiosit� sur tout ce qui tourne autour des variadic template qu'une r�elle n�cessit�.

    Merci d'avance

  2. #2
    Membre Expert
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, H�rault (Languedoc Roussillon)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par d�faut
    Mettre enable_if dans le param�tre template emp�che la d�duction automatique des types. Et comme on ne peut pas sp�cifier les types template d'un constructeur, cette solution n'en est pas viable (template variadique ou non).

    Par contre, on peut mettre enable_if autre part:
    - dans le type de retour (oups ) ou
    - dans la liste des param�tres templates: template<class... Args, class = std::enable_if_t<sizeof...(Args) <= SIZE>> Test(Args... args).

  3. #3
    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,

    De mani�re g�n�rale, il y a deux situations possibles :
    Soit tu veux adapter le comportement du constructeur par rapport au tydpe r�el du param�tre template, en gardant le m�me nombre de param�tres du m�me type
    Soit tu veux adapter le nombre (et le type �ventuellement) des param�tres en fonction du param�tre template.

    Dans le premier cas, il faudra placer std::enable_if dans la liste des param�tres, 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
    template <typename T>
    class MyClass{
    public:
        template <typename U =  T>
        MyClass(Type1 p1, Type2 p2, std::enable_if< TestOnU::value>::type * = nullptr){  //(*)
           /* ... */
        }
        template <typename U =  T>
        MyClass(Type1 p1, Type2 p2, std::enable_if< OtherTestOnU::value>::type * = nullptr){ //(*)
           /* ... */
        }
    };
    parce que le nombre et le type des param�tres explicites demand�s �tant identique , les deux versions ne sont pas consid�r�es comme �tant des surcharges valides.

    (*)TestOnU et OtherTestOnU seront sans doute diff�rents type_traits tels que d�finis dans le fichier <type_traits> (ou des type_traits personnalis�s)
    Dans le deuxi�me cas tu peux placer std::enable_if dans la liste des param�tres template sous une forme qui pourrait �tre 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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    template<typename T, size_t SIZE>
    class MathVector{
        using tab_t = std::array<T, SIZE>;
    public:
        /* constructeur par défaut, commun à tous les types concrets */
        MathVector(){
            tab_.fill(T{});
        }
        /* pour un vecteur contenant deux valeurs uniquement */
        template <typename U,
                         std::enable_if<SIZE == 2>::type>
        MathVector(U v1, U v2):MathVector({v1,v2}){
        }
        /* pour un vecteur contenant trois valeurs uniquement */
        template <typename U,
                         std::enable_if<SIZE == 3>::type>
        MathVector(U v1, U v2, U v3):MathVector({v1,v2,v3}){
        }
        /* pour un vecteur contenant quatre valeurs uniquement */
        template <typename U,
                         std::enable_if<SIZE == 4>::type>
        MathVector(U v1, U v2, U v3, U v4):MathVector({v1,v2,v3, v4}){
        }
        MathVector(std::initializer_list const & l):tab_{l}{
        }
        T operator[](size_t index) const{
            assert(index < SIZE);
            return tab_[index],
        }
        T & operator[](size_t index) {
            assert(index < SIZE);
            return tab_[index],
        }
        /* sans doute d'autres trucs sympa, comme les fonctions begin et end, dans différentes versions */
    private:
        tab_t tab_;
    };
    Dans ce cas, le nombre de param�tres attendus par le constructeur variant en fonction de la situation, chaque version est bel et bien � une surcharge valide

    NOTA: j'ai �crit ce code "de m�moire" car j'en ai effectivement mis un semblable en place r�cemment, mais je ne garanti pas que les tests indiqu�s soient ceux qui sont effectivement n�cessaires (en plus, je m'�tais fait des type_traits du genre isVec2, isVec3 et isVec4 pour la facilit� )
    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

  4. #4
    Membre Expert
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, H�rault (Languedoc Roussillon)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par d�faut
    Il faut savoir qu'avec des variadiques, mettre enable_if dans les param�tres de fonction ne fonctionne pas. Le compilateur va ignorer la variadique � cause de la pr�sence de valeur � droite et du coup on se retrouve avec une fonction variadique de taille 0.

  5. #5
    Membre �clair�
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels
    Secteur : Sant�

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Par d�faut
    Merci pour toutes vos r�ponses!

    Je viens de tester avec les std::enable_if et j'obtiens bien le comportement souhait�: � savoir qu'il y ait une erreur de compilation si le nombre d'arguments n'est pas correct. Vu que je ne souhaite pas des comportements diff�rents en fonction de la taille, je pense qu'il est plus sage pour moi d'utiliser les static_assert pour obtenir un message d'erreur plus compr�hensible.

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. Variadic templates et std::function
    Par white_tentacle dans le forum C++
    R�ponses: 36
    Dernier message: 08/07/2014, 10h38
  2. Constructeur variadic template
    Par DakM dans le forum Langage
    R�ponses: 5
    Dernier message: 14/07/2013, 02h32
  3. R�ponses: 4
    Dernier message: 30/05/2011, 19h38
  4. [C++0x] Variadic template : un constructeur par type
    Par Florian Goo dans le forum Langage
    R�ponses: 2
    Dernier message: 08/04/2009, 18h33
  5. classe template pb constructeur
    Par ouinih dans le forum Langage
    R�ponses: 6
    Dernier message: 16/08/2007, 18h02

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