2017-10-20 22 views
0

Je suis en train d'implémenter un simple modèle de classe Matrix Je voudrais l'instancier comme Matrix (data1, .., dataN) Fondamentalement, je pensais définir un template template qui prenait les 2 unsigned int comme paramètre de modèle, et en utilisant la liste d'initialisation pour en déduire le type de données contenant je en ce moment écrit ce simple début:Modèle matriciel du modèle

template<size_t N, size_t M> 
class Matrix { 

    public: 

    template<typename ...T> 
     constexpr Matrix<N,M>(T ... args) noexcept 
      : data{std::forward<T>(args)... } 
      { 
       static_assert(sizeof...(args) <= N*M, "Insufficent element for a Matrix "); 

      } 

    const auto getData()const { return data; } 


    private: 

    template<typename T> 
    std::valarray<T> data ; 
}; 

mais je suis une erreur ..

error: data member ‘data’ cannot be a member template std::valarray data ;

alors qu'est-ce que vous Penser à ? il existe un moyen de déduire le type de la matrice par son initialisation (paramètre passé au constructeur) et utiliser cette fois le long de toute définition de classe?

+2

Je ne sais pas si les variables membres peuvent être modélisées en C++ 14 ou au-delà, mais de toute façon pourquoi 'T' n'est pas un paramètre pour toute la classe? – user463035818

+0

Je m'attendrais à ce que 'typename T' soit le premier (ou le dernier) template template de la classe. – grek40

+0

parce que j'utiliserais la matrice pour instancier ces .. donc le paramètre de template de classe devrait être ... où je peux insérer le T ?? déduire quoi? –

Répondre

4

Il n'y a aucun moyen pour reporter le template <typename T> au constructeur. La matrice doit savoir ce que T va stocker avant d'appeler le constructeur, sinon il serait impossible de calculer la taille de l'objet matrice. Donc, vous devez déclarer la classe comme ceci:

template <typename T, std::size_t N, std::size_t M> 
class Matrix 
{ 
public: 
    // Constructors and stuff 

private: 
    std::valarray<T> data ; 
}; 

(note: il n'y a pas de type size_t en C++, mais il y a std::size_t)

La non-possibilité de déduire cette T est une chose agaçante. Les gens avaient l'habitude d'écrire des enveloppes comme std::make_pair, std::make_tuple, et ainsi de suite, en s'appuyant sur la capacité des fonctions à dériver leurs types d'arguments.

La prochaine norme a la caractéristique que vous voulez, appelée class template argument deduction. Il permet même un à guider le processus de déduction, comme ceci:

template <typename T, std::size_t N> 
struct array 
{ 
    T data[N]; 

    template <typename ... X> 
    array (X ... x) 
     : data{x...} 
    { } 
}; 

template <typename ... X> 
array(X ...) -> array<std::common_type_t<X...>, sizeof...(X)>; 

Unfortunatelly, dans votre cas, il est impossible de tirer N et M, donc vous devrez changer la signature du constructeur afin de pouvoir utiliser cette fonctionnalité .

+0

désolé je ne comprends pas ... de quelle manière? –

+1

@MarcoGhiani: il suffit de rendre le constructeur non basé sur un modèle, car par suggestion de lisyarus, vous aurez déjà 'T' comme paramètre de template de classe. Aussi maintenant 'data' sera un membre régulier, non modélisé –

+0

non je n'ai pas ... J'ai' template ' –