Breve:Assicurarsi che classe derivata dalla classe genitore CRTP implementa la funzione
voglio per assicurarsi che una classe derivata implementa una funzione di membro richiesto da una funzione all'interno della classe genitore CRTP.
dettaglio:
ho qualche codice come questo
class Base
{
public:
class Params
{
public:
virtual ~Params() {}
};
virtual void myFunc(Params& p) = 0;
};
template< typename T >
class CRTP : public Base
{
public:
virtual void myFunc(Base::Params& p) override
{
typename T::Params& typedParams = dynamic_cast<typename T::Params&>(p);
static_cast<T*>(this)->myFunc(typeParams);
}
};
class Imp : public CRTP<Imp>
{
public:
class Params : public CRTP<Imp>::Params
{
public:
virtual ~Params() {}
int x, y, z;
};
virtual void myFunc(Imp::Params& p);
};
L'intenzione è che posso avere più Imp
classi figlie tutti facendo cose diverse in myFunc
e accettando i propri parametri richiesti. L'interfaccia fornita da Base
viene quindi utilizzata dalle funzioni di livello superiore che necessitano solo di un puntatore/riferimento di tipo Base::Params
e Base
. Il mio problema è assicurarsi che qualsiasi Imp
fornisca un myFunc
specializzato. Per evitare la ricorsione infinita, Imp
deve implementare myFunc
.
Il mio primo tentativo è stata aggiunta una funzione virtuale pura al CRTP
virtual void myFunc(typename T::Params& p) = 0;
ma che non funziona come Imp
non è stato completamente definito quando CRTP
è in via di definizione. This question utilizza uno static_assert
che mi ha fatto pensare di fare lo stesso con lo static_assert
entro CRTP::myFunc
. Tranne che non sono sicuro di quale debba essere l'espressione nell'asserzione statica per una funzione non statica.
- Posso utilizzare uno
static_assert
per quello che mi serve? - È il modo migliore/più pulito per garantire che la classe derivata abbia la funzione necessaria?
- Sono stato portato via con il mio design di classe e c'è un modo migliore di fare le cose?
Grazie.
non si può usare qualche magia SFINAE per stabilire se 'Imp :: Param' è diverso da' Base :: Param' e che 'Imp :: myFunc()' accetta 'Imp :: Param' come argomento? – Walter
@Walter per il secondo, se c'è ereditarietà, avrà falsi positivi. Per il primo, potresti non volerlo richiedere. – Yakk
A parte: perché stai colando static a 'T const *' da un metodo non-'const'? O 'myFunc' dovrebbe essere' const' in 'Base' e' CRTP', o dovresti chiamare 'static_cast' nell'implementaiton 'CRTP'. –
Yakk