Posso usare boost :: abilita_if su una funzione membro?
Domanda
Sto scrivendo una classe di modelli e voglio consentire a un metodo aggiuntivo di esistere solo per un certo tipo di modello. Attualmente il metodo esiste per tutti i tipi di modelli, ma provoca un errore di compilazione per tutti gli altri tipi.
Complicando questo è che è un operatore sovraccarico (). Non sono sicuro se quello che voglio fare sia effettivamente possibile qui.
Ecco quello che ho ora:
template<typename T, typename BASE>
class MyClass : public BASE
{
public:
typename T& operator() (const Utility1<BASE>& foo);
typename T const& operator() (const Utility2<BASE>& foo) const;
};
voglio il T&
versione sempre disponibile, ma il T const&
versione disponibile solo se Utility2<BASE>
è valido. In questo momento, entrambi i metodi esistono, ma il tentativo di utilizzare la versione const fornisce uno strano errore di compilazione se Utility2<BASE>
è invalido. Preferirei avere un errore sensato, o persino un errore "nessuna funzione di membro".
È possibile?
MODIFICARE: Dopo aver letto i documenti di boost, ecco cosa ho escogitato e sembra funzionare:
template<typename T, typename BASE>
class MyClass : public BASE
{
public:
typename T& operator() (const Utility1<BASE>& foo);
template<typename U>
typename boost::enable_if<boost::is_same<Utility2<BASE>, U>, T>::type const &
operator() (const U& foo) const;
};
In modo che quel metodo non esista a meno che qualcuno non cerchi di usarlo con Utility2 e può creare un utilità2 solo se è valido per quel tipo di base. Ma quando non è valido per quel tipo di base, Myclass non perderà tempo a creare il metodo degli accessori.
Soluzione
Sì, questo è possibile, ma non con il parametro del modello di classe direttamente. boost::enable_if
può essere utilizzato solo con un parametro modello sul metodo stesso. Quindi, con un piccolo utilizzo di TypeDef:
template<typename T, typename BASE>
class MyClass : public BASE
{
public:
typedef Utility2<BASE> util;
typename T& operator() (const Utility1<BASE>& foo);
template<typename U>
typename boost::enable_if<boost::is_same<util, U>, T>::type const &
operator() (const U& foo) const;
};
Funziona, perché Utility2 può essere creata solo da un determinato tipo di base. Quindi, se il tipo di base è qualcos'altro, la versione const dell'operatore () non esiste.
Quindi, è una cosa molto minore. Non mi guadagna molto. Ma era bello da fare.