2009-08-14 8 views
1

Si je veux créer un modèle de fonction, où le paramètre de modèle n'est pas utilisé dans la liste des arguments, je peux le faire ainsi:modèles de l'opérateur en C++

template<T> 
T myFunction() 
{ 
//return some T 
} 

Mais l'invocation doit spécifier le « T 'utiliser, car le compilateur ne sait pas comment le résoudre.

myFunction<int>(); 

Mais, supposons que je voulais faire quelque chose de similaire, mais pour l'opérateur '[]'. modèle

T SomeObject::operator [ unsigned int ] 
{ 
    //Return some T 
} 

Est-il possible d'invoquer cet opérateur? Cela ne semble pas valide:

SomeObject a; 
a<int>[3]; 

Répondre

6

Cela devrait fonctionner:

class C 
{ 
public: 
    template <class T> 
    T operator[](int n) 
    { 
     return T(); 
    } 
}; 

void foo() 
{ 
    C c; 

    int x = c.operator[]<int>(0); 
} 

Mais il est sans valeur réelle parce que vous auriez toujours de préciser le type, et il ressemble à un appel de fonction très laid - le point d'une surcharge de l'opérateur est ressembler à une invocation d'opérateur.

+0

Bien, je ne savais pas que vous pouviez faire ça! Mais oui, le faire de cette façon défait la gentillesse d'utiliser une surcharge de l'opérateur du tout. – Scott

+1

En effet. Habituellement, il est renommé 'get()'. – GManNickG

+0

L'opérateur [] n'est-il pas censé renvoyer une référence? – navigator

2

Vous pouvez utiliser a.operator [] <int> (1); Mais pourquoi voulez-vous cela?

1

Cela ne peut être une solution, mais vous pouvez appeler directement l'opérateur en tant que tel:

a.operator[](3);

J'ai essayé en g ++ avec le test suivant:

class MyClass { 
public: 
    template<class T> 
    T operator[](unsigned int) { 
     // do something 
     return T(); 
    } 
}; 

int main(int argc, char* argv[]) { 
    MyClass test; 
    test.operator[]<int>(0); 
    //test<int>[0]; // doesn't compile, as you mentioned 
    return 0; 
}
+0

C'était vraiment remarquable à quelle vitesse cela a été répondu. Pendant que je tapais ceci, j'ai continué à voir des réponses postées, et toutes pratiquement identiques. Je suppose que je n'étais pas assez rapide :) – John

1

Si vous devez define operator [] alors définissez probablement le template au niveau de la classe. Quelque chose comme ceci:

template<class T> 
class C 
{ 
public: 
    T operator[](int n) 
    { 
     return T(); 
    } 
}; 

int main() 
{ 
    C<int> c; 

    int x = c[0]; 

    return 0; 
} 
+0

J'avais besoin de ça dans une classe qui gère un tas de types différents à travers une seule instance, plutôt qu'un tas de classes spécialisées qui gèrent leurs propres instances. Je pense que je vais devoir aller pour le formulaire Object.func ()! – Scott

0

j'ai du mal à venir avec un exemple où cela serait nécessaire (ne pouvait pas vous venez surcharge l'opérateur à la place?), Mais voici quand même mes pensées:

Étant donné que vous ne pouvez pas utiliser la syntaxe de l'opérateur infix avec des opérateurs modélisés, vous pouvez effectuer l'instanciation de modèle avant que vous appelez l'opérateur. Un proxy peut être un moyen de le faire.

class some_class { 
private: 
    template<class T> class proxy { 
    some_class* that_; 
    public: 
    proxy(some_class* that) : that_(that) {} 
    T& operator[](std::size_type idx) {return that->get<T>(idx);} 
    }; 

    template<class T> class const_proxy { 
    some_class* that_; 
    public: 
    proxy(const some_class* that) : that_(that) {} 
    const T& operator[](std::size_type idx) const {return that->get<T>(idx);} 
    }; 

    template< typename T >  proxy<T> get_array()  {return proxy<T>(this);} 
    template< typename T > const_proxy<T> get_array() const {return proxy<T>(this);} 

    template< typename T >  T& get(std::size_t idx)  {/* whatever */} 
    template< typename T > const T& get(std::size_t idx) const {/* whatever */} 
}; 

// This is a lousy use case. 
// Did I already say I have a hard time imagining how to use this? 
template< typename T > 
void f(some_class& some_object, sid::size_t idx) 
{ 
    T& = some_object.get_array<T>()[idx]; 
} 
4

Boost.Program_options utilise cette syntaxe propre:

int& i = a["option"].as<int>(); 

ce qui est obtenu avec quelque chose comme ceci:

class variable_value 
{ 
public: 
    variable_value(const boost::any& value) : m_value(value) {} 

    template<class T> 
    const T& as() const { 
     return boost::any_cast<const T&>(m_value); 
    } 

    template<class T> 
    T& as() { 
     return boost::any_cast<T&>(m_value); 
    } 

private: 
    boost::any m_value; 
}; 

class variables_map 
{ 
public: 
    const variable_value& operator[](const std::string& name) const 
    { 
     return m_variables[name]; 
    } 

    variable_value& operator[](const std::string& name) 
    { 
     return m_variables[name]; 
    } 

private: 
    std::map<std::string, variable_value> m_variables; 
}; 

Vous pouvez adapter cette idée en fonction de vos besoins.