2017-04-03 2 views
1

J'ai le problème suivant (voir le code ci-dessous).C++ 11 méthode du modèle variadique complètement la méthode de la classe de base de l'ombre?

Dans une classe qui hérite d'une classe de base, je souhaite pouvoir avoir deux implémentations de operator(). Celui qui prend des entiers, celui qui prend des "indices", voir la classe Index simple. Le operator(ints...) sera dans la classe des enfants, alors que je dois avoir la operator(Index...) dans la classe parente (également avec différents types de retour.)

Le code ci-dessous n'est pas la conception exacte, mais un exemple de travail minimal expliquant le dernier problème .

Le problème est, si je mets operator(Index...) dans la classe enfant, tout est bon. Si je le mets dans la classe de base, je reçois une erreur de compilation:

error: no match for call to ‘(Tensor<1, int>) (Index<'i'>&)’ 

quand je l'appelle vec(i) et la fin de la main(). Je comprends que le compilateur ne trouve pas la bonne méthode, mais pourquoi? Existe-t-il une règle de "masquage" associée aux modèles variés?

Merci!

#include <iostream> 
#include <type_traits> 

template<char i> 
class Index{ 
public: 
    Index(){}; 
}; 

template<int order, typename T, class tensor_type> 
class Tensor_traits{ 
    public: 

     //// here, doesn't compile ! ! 
    //template <char i> 
    //T&operator()(Index<i> &ii){ 
    //std::cout << "puet" << std::endl; 
    //} 
}; 


template<int order, typename T> 
class Tensor : public Tensor_traits<order, T, Tensor<order, T>> { 
    private: 
    int data[3] = {1,2,3}; 
    public: 
    Tensor(){}; 

    template <typename... Idx> 
     typename std::enable_if<std::is_same<Idx...,int>::value 
     or std::is_same<Idx...,unsigned int>::value 
     or std::is_same<Idx...,size_t>::value, T&>::type 
     operator()(const Idx&... idx){ 
     return data[0]; //dummy here, actually i do other stuff ! 
     } 

    // here, works! 
    template <char i> 
     T&operator()(Index<i> &ii){ 
     std::cout << "puet" << std::endl; 
     } 

}; 


int main() { 

    Tensor<1,int> vec1; 

    std::cout<< vec1(1) << std::endl;; 

    Index<'i'> i; 

    vec1(i); 
} 

Répondre

2

Essayez d'ajouter

using Tensor_traits<order, T, Tensor<order, T>>::operator(); 

ou (suggérée par Yakk (merci) d'avoir Base pour d'autres usages)

using Base = Tensor_traits<order, T, Tensor<order, T>>; 
using Base::operator(); 

dans Tensor

Le problème est pas la classe de base est une classe de modèle; le problème est que la classe dérivée définit une autre fonction de méthode operator() qui masque la méthode operator() héritée.

Pour vérifier cela, supprimez le operator() défini dans la classe dérivée et vous pouvez voir que, également sans using, vous pouvez utiliser le operator() de la classe de base.

L'utilisation de using affiche la operator() de la classe de base, lorsqu'un operator() est défini dans la classe dérivée, vous pouvez donc utiliser les deux.

+1

Moi, je fais d'abord 'en utilisant Base = Tensor_traits >;' puis 'en utilisant Base :: operator();'. Parce que mon cerveau n'est pas assez intelligent pour prouver instantanément 'Tensor_traits >' est juste la base de 'Tenseur ', et en le nommant 'Base' l'intention est plus claire. – Yakk

+0

@Yakk - également pour éviter la duplication de code dans le cas de 'using 'pour plusieurs méthodes de base? – max66

+0

et dans les constructeurs etc. Si ce n'était pas le CRTP, ce que je fais habituellement est de le faire dans la liste d'arguments du template comme: ', class Base = Tensor_traits >', mais avec CRTP qui ne fonctionne pas . – Yakk