2010-06-02 8 views
3

je tente de faire un usage intensif de modèles pour envelopper une classe d'usine:modèle de fonction C de -> le passage d'un modèle de classe comme modèle argument

La classe d'emballage (c.-à-CLASSA) obtient la classe enveloppé (c.-à-ClassB) via un argument de template pour fournir une 'pluggability'.

De plus, je dois fournir une classe interne (innerA) qui hérite de la classe interne enveloppée (innerB).

Le problème est la "version gcc 4.4.3 (Ubuntu 4.4.3-4ubuntu5)" message d'erreur du g ++ suivant:

[email protected]:~/Development/cppExercises/functionTemplate$ g++ -o test test.cpp 
test.cpp: In static member function ‘static classA<A>::innerA<iB>* classA<A>::createInnerAs(iB&) [with iB = int, A = classB]’: 
test.cpp:39: instantiated from here 
test.cpp:32: error: dependent-name ‘classA::innerA<>’ is parsed as a non-type, but instantiation yields a type 
test.cpp:32: note: say ‘typename classA::innerA<>’ if a type is meant 

Comme vous pouvez le voir dans la définition de createInnerBs méthode, i intention de passer un argument non-type. Donc l'utilisation de typename est fausse!

Le code de test.cpp est ci-dessous:

class classB{ 
public: 
    template < class iB> 
    class innerB{ 
    iB& ib; 
    innerB(iB& b) 
     :ib(b){} 
    }; 

    template<template <class> class classShell, class iB> 
    static classShell<iB>* createInnerBs(iB& b){ 
    // this function creates instances of innerB and its subclasses, 
    // because B holds a certain allocator 

    return new classShell<iB>(b); 
    } 
}; 

template<class A> 
class classA{ 
    // intention of this class is meant to be a pluggable interface 
    // using templates for compile-time checking 
public: 
    template <class iB> 
    class innerA: A::template innerB<iB>{ 
    innerA(iB& b) 
     :A::template innerB<iB>(b){} 
    }; 

    template<class iB> 
    static inline innerA<iB>* createInnerAs(iB& b){ 
    return A::createInnerBs<classA<A>::template innerA<> >(b); // line 32: error occurs here 
    } 
}; 

typedef classA<classB> usable; 
int main (int argc, char* argv[]){ 
    int a = 5; 
    usable::innerA<int>* myVar = usable::createInnerAs(a); 

    return 0; 
} 

S'il vous plaît aidez-moi, j'ai été confronté pendant plusieurs jours à ce problème. Est-ce simplement impossible, qu'est-ce que j'essaie de faire? Ou ai-je oublié quelque chose?

Merci, Sema

Répondre

2

Ligne 32 doit lire:

return A::template createInnerBs<innerA>(b); 

depuis createInnerBs dépend du paramètre du modèle A. Vous devrez également rendre les constructeurs innerA et innerB publics.

+1

ok merci, en règle générale pour moi: Toujours utiliser typename/template pour spécifier des types ou des modèles dans les spécificateurs de noms imbriqués lorsque des modèles sont impliqués. correct? – sema

+0

Y a-t-il une raison logique pour que ce soit 'A :: template smth' et non' template A :: smth' en C++? –

+1

@TigranSaluev: Oui, vous spécifiez que 'smth' est un modèle, donc le mot-clé doit être associé à cela. Sinon, vous ne pourrez pas spécifier d'autres modèles imbriqués, 'A :: template B :: template C :: whatever' –

1

Voici le code corrigé qui compile pour moi:

class classB{ 
public: 
    template < class iB> 
    class innerB{ 
    iB& ib; 
    public: 
    innerB(iB& b) 
     :ib(b){} 
    }; 

    template<template <class> class classShell, class iB> 
    static classShell<iB>* createInnerBs(iB& b){ 
    // this function creates instances of innerB and its subclasses, 
    // because B holds a certain allocator 

    return new classShell<iB>(b); 
    } 
}; 

template<class A> 
class classA{ 
    // intention of this class is meant to be a pluggable interface 
    // using templates for compile-time checking 
public: 
    template <class iB> 
    class innerA: public A::template innerB<iB>{ 
    public: 
    innerA(iB& b) 
     : A::template innerB<iB>(b){} 
    }; 

    template<class iB> 
    static inline innerA<iB>* createInnerAs(iB& b); 
}; 

template<class A> 
template<class iB> 
inline classA<A>::innerA<iB>* classA<A>::createInnerAs(iB& b) 
{ 
    return A::template createInnerBs<classA::template innerA>(b); 
} 

typedef classA<classB> usable; 
int main (int argc, char* argv[]){ 
    int a = 5; 
    usable::innerA<int>* myVar = usable::createInnerAs(a); 

    return 0; 
} 

Même si je pense que vous ... Mais les choses trop compliquer, je ne comprends pas bien votre cas d'utilisation.

Questions connexes