2012-02-27 9 views
9

È possibile definire due classi differenti (per numero di argomenti del modello) con lo stesso nome?Modelli di classi con nomi duplicati?

Qui è quello che sto cercando di fare:

namespace MyNamespace 
{ 

template<class TRet> 
class FunctionObject 
{ 
    typedef typename TRet ReturnType; 
    virtual ReturnType const operator()() const = 0; 
}; 


template<class TRet, class TArg0> 
class FunctionObject 
{ 
    typedef typename TRet ReturnType; 
    typedef typename TArg0 FirstArgumentType; 
    virtual ReturnType const operator()(FirstArgumentType const &arg) const = 0; 
}; 

} 

ottengo un errore di nota troppi argomenti template alla fine della chiusura staffa della seconda definizione FunctionObject struct.

So che questo può essere fatto in C#, ma non ero sicuro di C++. Qualcuno può per favore fare un po 'di luce qui?

+1

Cosa vuoi dire che può essere fatto in C#? C# non ha modelli. –

+0

Penso che significano con generici in C#. –

+0

Concetto di generici in C#. – user460762

risposta

11

Penso specializzazione parziale farebbe il trucco:

namespace MyNamespace { 

    template<class TRet, class TArg0> 
    class FunctionObject 
    { 
     typedef typename TRet ReturnType; 
     typedef typename TArg0 FirstArgumentType; 
     virtual ReturnType const operator()(FirstArgumentType const &arg) const = 0; 
    }; 

    template<class TRet> 
    class FunctionObject<TRet,void> 
    { 
     typedef typename TRet ReturnType; 
     virtual ReturnType const operator()() const = 0; 
    }; 

} 

si potrebbe anche iniziare con un modello primaria con più di un parametro.

Penso che C++ 11 i suoi modelli variadici consentano che questo sia più elegante, ma non avevo avuto il tempo di giocare con questo, quindi è meglio lasciarlo a qualcun altro da mostrare.

+0

Sì, ci ho pensato, ma se voglio creare un'altra classe con tre argomenti di template allora dovrò modificare quelli attuali per includere argomenti void per quelli inapplicabili. Buon suggerimento però Grazie. – user460762

+0

@ user460762: Sì, sarà necessario iniziare con il numero massimo di argomenti che si desidera essere in grado di gestire. Alcune persone si sono occupate di questo affidandosi a macro meta hacker. Ma, come ho detto, i modelli variadici farebbero il trucco. – sbi

+1

Perché non definire un solo modello di classe e fornire un argomento predefinito per il secondo parametro del modello? – Nawaz

1

credo che qualcosa di simile a questo sarà anche funzionare, ma con classi separate non può essere quello che stai cercando:

namespace MyNamespace 
    { 

     class AbstractFunctionObject 
     { 
     //shared functionality here 
     }; 

     template<class TRet> 
     class ConcreteFunctionObjectA : AbstractFunctionObject 
     { 
     typedef typename TRet ReturnType; 
     virtual ReturnType const operator()() const = 0; 
     }; 


     template<class TRet, class TArg0> 
     class ConcreteFunctionObjectB : AbstractFunctionObject 
     { 
     typedef typename TRet ReturnType; 
     typedef typename TArg0 FirstArgumentType; 
     virtual ReturnType const operator()(FirstArgumentType const &arg) const = 0; 
     }; 

    } 
+0

Mentre questo sembra davvero possibile, è anche inutile.A cosa serve una classe di base polimorfica vuota? – sbi

+0

Non sarebbe vuoto. Se l'OP ha scelto questa immagine di percorso, sposterebbe la funzionalità che sarebbe condivisa da tutti i modelli variadici alla classe base. È difficile indovinare le intenzioni, quindi l'ho lasciato vuoto. –

+0

Cosa potrebbe esserci in un Functor, ma 'operator()()' più alcuni typedef? – sbi

5

Penso che si possa farlo funzionare con un modello di classe, fornendo tipo predefinito argomento per il secondo parametro template come:

struct null_type {}; 

template<class TRet, class TArg0 = null_type> 
class FunctionObject 
{ 
    typedef typename TRet ReturnType; 
    typedef typename TArg0 FirstArgumentType; 

    //both functions here 
    virtual ReturnType const operator()() const = 0; 

    virtual ReturnType const operator()(FirstArgumentType const &arg) const = 0; 
}; 
+3

Tipo di nella giusta direzione ma non del tutto lì. Ciò consentirà l'uso del modello con uno o due argomenti, ma nella domanda originale la definizione dei due modelli sembra essere molto diversa (membri diversi, firma diversa per 'operator()') che sembra indicare che * specializzazione * sarebbe la strada da percorrere Rispetto alla risposta di sbi, questa ha la bella caratteristica di creare un * unique * type ('null_type' dovrebbe essere univoco) e quindi consentire l'uso di' void' come secondo argomento della specializzazione in due argomenti, che è bello (+1 per quello) –

+0

@David: Questa è davvero una grave mancanza della mia idea. Dovrei aggiustarlo. – sbi

+0

Sicuramente una soluzione intelligente. Solo una cosa da considerare con questo approccio è che ogni classe che eredita questa classe/struttura dovrà implementare tutti gli operatori vuoti/inapplicabili. Quindi è un compromesso tra una soluzione elegante (meno prolissa) e meno oneri per la futura impiantazione. – user460762

6

per mostrare suggerito soluzione di modello variadic di SBI:

namespace MyNamespace { 

    template<typename...> FunctionObject; 

    template<class TRet, class TArg0> 
    class FunctionObject<TRet,TArg0> 
    { 
     typedef typename TRet ReturnType; 
     typedef typename TArg0 FirstArgumentType; 
     virtual ReturnType const operator()(FirstArgumentType const &arg) const = 0; 
    }; 

    template<class TRet> 
    class FunctionObject<TRet> 
    { 
     typedef typename TRet ReturnType; 
     virtual ReturnType const operator()() const = 0; 
    }; 

} 

Ora è possibile aggiungere specializzazioni nell'ordine desiderato, senza modificare gli altri modelli (a meno che il numero/tipo di parametri del modello non sia in conflitto).

+0

Sì, '+ 1', per questo è più semplice del mio. Se hai accesso a un compilatore che lo supporta. – sbi

Problemi correlati