2009-11-27 12 views
17
  1. Esiste l'equivalente di <? extends T>, <? super T> in C++?Esiste l'equivalente di <? extends T>, <? super T> in C++?

  2. Inoltre, lo <? extends T>, <? super T> funziona anche se T è un'interfaccia in Java?

+0

Che cosa avete bisogno di questo per? Potrebbe esserci una soluzione più semplice e più simile a C++ che provare ad emulare questa funzionalità Java – jalf

risposta

2

risposta alla prima parte: Restrict Template Function

JesperE ha la risposta giusta per il 2 ° parte.

+0

Seguire la regola che se la classe passata come argomento ha i metodi necessari definiti è un controllo a prova di errore. Una classe approvata avrà sicuramente tutte le funzioni necessarie. Ma il contrario non è sempre vero. Se hai qualcosa come <? estende T> quindi è infallibile perché stiamo specificando esplicitamente la gerarchia delle classi – user855

+0

@ajay: se vuoi limitare il parametro type ad essere una classe base perché usi esattamente l'interfaccia della classe base, allora devi renderla un modello? Puoi operare su una classe base per riferimento? Questo ti darebbe il tipo di sicurezza che stai cercando. I modelli consentono di definire operazioni che funzionano su tipi che non devono necessariamente provenire dalla stessa gerarchia. Questo è il loro potere. Se questo non è fattibile nella tua situazione, forse potresti aggiornare la domanda con maggiori dettagli su cosa stai cercando di fare e quali funzionalità di C++ potrebbero aiutarti a raggiungere questo obiettivo. –

+0

? extends significa qualsiasi sottoclasse del basetype. – TofuBeer

5

Per rispondere alla seconda domanda: sì. Per quanto riguarda i generici, le interfacce sono trattate come le classi reali.

Lascerò la prima domanda alle persone più esperte del C++.

12

Non ha uno zucchero sintattico piuttosto bello come in Java ma è gestibile bene con boost/type_traits. Vedere http://www.boost.org/doc/libs/1_40_0/libs/type_traits/doc/html/index.html per maggiori informazioni.

#include <boost/type_traits.hpp> 
#include <boost/static_assert.hpp> 

class Base {}; 
class Derived_from_Base : public Base {}; 
class Not_derived_from_Base {}; 

template<typename BASE, typename DERIVED> 
void workOnBase() 
{ 
    BOOST_STATIC_ASSERT((boost::is_base_of<BASE, DERIVED>::value)); 
} 

int main() 
{ 
    workOnBase<Base, Derived_from_Base>();  // OK 
    workOnBase<Base, Not_derived_from_Base>(); // FAIL 
    return 0; 
} 

1> D: ... \ main.cpp (11): l'errore C2027: uso di tipo non definito 'boost :: STATIC_ASSERTION_FAILURE' 1> con 1> [ 1> x = false 1>]

3

È possibile limitare l'intervallo di un parametro di modello in C++ utilizzando i vari meccanismi di tratti, di cui sono disponibili le implementazioni in Boost.

In genere non lo è: il motivo per cui la sintassi esiste in Java e C# è che usano i generici, non i modelli.

I generici Java generano codice condiviso che utilizza l'invio virtuale dal tipo base, anziché generare codice per ogni tipo utilizzato come argomento modello. Di solito, si utilizza la restrizione per consentire di chiamare metodi sugli oggetti del tipo utilizzato come parametro del modello.

Poiché C++ genera codice per ogni tipo utilizzato come parametro di modello, non è necessario conoscere un tipo di base per essi.

Ad esempio, una classe template per una matrice utilizzerà gli operatori +, -, * sul tipo di destinazione. In può quindi essere utilizzato per qualsiasi tipo che supporti tali operatori. Se è stato arbitrariamente limitato a double s e int s, non è possibile utilizzare il modello con un complex<double> o eseguire un test con un tipo che supporta l'aritmetica a intervalli, anche se tali tipi forniscono tali operatori e la libreria di matrici sarebbe valida usando loro.

La possibilità di lavorare su tipi arbitrari che hanno la stessa forma è la potenza dei modelli e li rende più utili. Spetta al codice cliente decidere se è valido utilizzare quel modello con quel tipo (purché compili) e il cliente abbia sempre ragione. L'incapacità di lavorare su tipi arbitrari che hanno la stessa forma e l'obbligo di specificare restrizioni per chiamare metodi diversi da quelli di java.lang.Object è una debolezza dei farmaci generici.

2

Questo è uno extension che è stato rimosso dallo standard bozza di C++ 0x perché "non era pronto".Tuttavia, è possibile simulare ciò usando affermazioni statiche (che è una parte di C++ 0x e Boost come le persone hanno menzionato qui).

1

questo ha funzionato per me:

#include <iostream> 

class MyBase {}; 
class A : public MyBase {};  
class B {}; 

template <class T> 
typename std::enable_if<!std::is_base_of<MyBase, T>::value>::type 
Foo(T &v) { 
    std::cout << "Foo 1" << std::endl; 
} 

template <class T> 
typename std::enable_if<std::is_base_of<MyBase, T>::value>::type 
Foo(T &v) { 
    std::cout << "Foo 2" << std::endl; 
} 

int main() { 
    A a; 
    B b; 
    Foo(a); 
    Foo(b); 
    return 0; 
} 
+0

la domanda precede 'is_base_of' (e' enable_if' per quella materia), oggi questa dovrebbe essere la soluzione predefinita – Ap31

Problemi correlati