2016-03-07 5 views
0

J'écris actuellement un programme fonctionnant avec NURBS surfaces, où vous pouvez effectuer des algorithmes dans deux directions (U et V). Pour éviter la duplication de code, j'ai essayé d'utiliser des modèles, mais je ne suis en aucun cas expérimenté en les utilisant. Voici un petit exemple de ce que je voudrais faire:getters spécialisés de modèle C++

#include <iostream> 

enum class Dir { 
    U, V 
}; 

struct Foo { 

    unsigned cu, cv; 

    Foo(unsigned cu, unsigned cv) : cu(cu), cv(cv) {}; 

    template<Dir> 
    const Dir otherDir(); 

    template<> 
    const Dir otherDir<Dir::V>() { 
     return Dir::U; 
    } 

    template<> 
    const Dir otherDir<Dir::U>() { 
     return Dir::V; 
    } 

    template<Dir> 
    unsigned count(); 

    template<> 
    unsigned count<Dir::U>() { 
     return cu; 
    } 

    template<> 
    unsigned count<Dir::V>() { 
     return cv; 
    } 

    template<Dir d> 
    unsigned totalCount() { 
     auto c = count<d>(); 
     auto cOther = count<otherDir<d>()>(); 
     return c * cOther; 
    } 

}; 

int main() { 
    Foo f(3,2); 
    std::cout << (f.count<Dir::U>() == 3) << std::endl; 
    std::cout << (f.otherDir<Dir::U>() == Dir::V) << std::endl; 
    std::cout << f.totalCount<Dir::U>() << std::endl; 
} 

mais cela ne compile pas en raison de la dernière ligne principale (VS2015, mais je ne pense pas que ce soit la faute du compilateur):

1>...\main.cpp(42): error C2672: 'Foo::count': no matching overloaded function found 
1>...\main.cpp(52): note: see reference to function template instantiation 'unsigned int Foo::totalCount<Dir::U>(void)' being compiled 
1>...\main.cpp(42): error C2975: 'unnamed-parameter': invalid template argument for 'Foo::count', expected compile-time constant expression 
1>...\main.cpp(27): note: see declaration of 'unnamed-parameter' 
1>...\main.cpp(43): error C3536: 'cOther': cannot be used before it is initialized 

seule façon que je me rapprochais de la fonctionnalité ci-dessus est en spécifiant à la fois la direction principale ainsi que l'autre sens que les arguments de modèle comme celui-ci:

struct Foo { 

    ... 

    template<Dir d, Dir otherD> 
    unsigned totalCount() { 
     auto c = count<d>(); 
     auto cOther = count<otherD>(); 
     return c * cOther; 
    } 

}; 

int main() { 
    Foo f(3,2); 
    std::cout << f.totalCount<Dir::U, Dir::V>() << std::endl; 
} 

mais cela ne semble pas être très élégant .

+0

Side note: Attention à VS extension non standard, ce qui précède ne compile pas avec g ++, même sans 'totalCount' (voir http://stackoverflow.com/questions/2097811/c-syntax-for-explicit-specialization-of-a-template-function-in-a-template-clas). – Holt

+0

Et je ne vois pas vraiment le point d'avoir un gabarit ici, pourquoi ne pas simplement passer la direction comme argument à la fonction? – Holt

+0

'otherDir ()' n'est pas 'constexpr' et ne peut pas être utilisé dans un argument template. – Jarod42

Répondre

0

otherDir<d>() n'est pas constexpr et ne peut pas être utilisé dans l'argument modèle (count<otherDir<d>()>()).

Vous pouvez ajouter constexpr (et static) à cette méthode, ou utiliser de vieux struct pour gérer que:

template <Dir> struct otherDir; 

template<> 
struct otherDir<Dir::U> 
{ 
    static constexpr Dir value = Dir::V; 
}; 

template<> 
struct otherDir<Dir::V> 
{ 
    static constexpr Dir value = Dir::U; 
}; 

Demo

+0

Merci d'avoir aidé 'otherDir'' constexpr static' aidé. – Nakamp

0

Probablement, problème ici est:

auto cOther = count<otherDir<d>()>(); 

modèles sont "résolus" dans la compilation. Vous devez utiliser constexpr pour otherDir<d>() parce que simplement const ne signifie pas que la méthode peut être évaluée à la compilation.

Une approche plus traditionnelle consiste à avoir la structure otherDir au lieu de la méthode. Créer un modèle de structure, deux instanciations seraient avec static const value = V ou U.

Ou vous pouvez remplacer enum avec des structures vides.

Ou, ce qui est encore mieux, vous pouvez essayer de l'implémenter sans modèles et créer une classe pour la dimension et avoir un objet pour chaque dimension.