2014-04-15 14 views
6

Operando sotto la regola del "non c'è mai nulla di nuovo sotto il sole," Dubito che io sono la prima persona a venire con questo trucco. Ho pensato che mi sarei imbattuto in qualcosa di online documentandolo alla fine, ma non l'ho ancora fatto, quindi ho pensato che avrei chiesto.Questo modello SFINAE ha un nome?

Il suo scopo è abilitare selettivamente alcune funzioni a condizione che siano rilevanti, senza utilizzare una classe derivata.

Esiste un nome per questo motivo? E qualcuno ha qualche informazione utile su questo modello o su un modello che funziona in modo simile?

template<typename T, size_t N> 
class Point { 
public: 
    template<size_t P, typename T2=void> 
    using Enable2D = typename std::enable_if<P == 2 && N == P, T2>::type; 
    template<size_t P, typename T2=void> 
    using Enable3D = typename std::enable_if<P == 3 && N == P, T2>::type; 
    template<size_t P, typename T2=void> 
    using Enable4D = typename std::enable_if<P == 4 && N == P, T2>::type; 
    template<size_t P, typename T2=void> 
    using Enable2DOrHigher = typename std::enable_if<P >= 2 && N == P, T2>::type; 
    template<size_t P, typename T2=void> 
    using Enable3DOrHigher = typename std::enable_if<P >= 3 && N == P, T2>::type; 
    template<size_t P, typename T2=void> 
    using Enable4DOrHigher = typename std::enable_if<P >= 4 && N == P, T2>::type; 

    //Example use cases 
    template<size_t P=N> 
    static Enable2D<P, Point> withAngle(T angle, T magnitude = 1); 
    template<size_t P=N> 
    static Enable3D<P, Point> fromAngles(T psi, T theta, T magnitude = 1); 

    template<size_t P=N> 
    Enable2DOrHigher<P, T> const& x() const; 
    template<size_t P=N> 
    Enable2DOrHigher<P, T> const& y() const; 
    template<size_t P=N> 
    Enable2DOrHigher<P> setX(T const& t); 
    template<size_t P=N> 
    Enable2DOrHigher<P> setY(T const& t); 

    template<size_t P=N> 
    Enable3DOrHigher<P, T> const& z() const; 
    template<size_t P=N> 
    Enable3DOrHigher<P> setZ(T const& t); 

    template<size_t P=N> 
    Enable4DOrHigher<P, T> const& w() const; 
    template<size_t P=N> 
    Enable4DOrHigher<P> setW(T const& t); 
}; 
+0

È un'idea interessante, in pratica parametrizza i puntatori funzione membro. In javascript, è possibile creare l'oggetto "prototipo" e quindi creare condizionatamente determinate funzioni membro. Non ho visto nulla di simile in C++. Curioso di vedere le risposte ... –

+0

Il caso d'uso motivante per questo era che avevamo anche classi di box e linee multidimensionali che prendevano un punto standard, ma avevamo precedenti classi derivate per point2 e point3, quindi l'utile punto 2d e 3d le funzioni non erano accessibili sia alle classi stesse (a meno che non ne dovessimo ricavare anche quelle, nel qual caso sarebbe una reimplementazione perché i membri erano cambiati e c'era molto codice comune, DRY), ma anche a qualsiasi parte di codice che utilizzava gli algoritmi di casella e linea. Quindi abbiamo ritenuto che l'uso di SFINAE fosse più pulito, anche se rendeva le funzioni esposte leggermente incoerenti. – OmnipotentEntity

+0

Perché l'uso ripetuto di 'enable_if' può diventare un pattern? Questa è una tipica applicazione di 'enable_if' - ad es. consideri [descrizione di cppreference] (http://en.cppreference.com/w/cpp/types/enable_if) "* rimuovi condizionatamente funzioni e classi dalla risoluzione di sovraccarico basata sui tratti del tipo e per fornire overload e specializzazioni di funzioni separate per tratti di tipo diverso * "... sembra comprendere ciò che hai fatto del tutto adeguatamente. –

risposta

4

Io non lo definirei un modello, ma è una tecnica nota.

Parzialmente A riferiti come interfaccia condizionale questa tecnica riguarda principalmente il problema di una fase di compilazione commutazione meccanismo per accendere e spegnere le interfacce di una classe. Il processo generale fornisce gli strumenti per commutare anche l'esistenza dei membri (così nasce il termine compilazione condizionale).

La tecnica è più o meno implementato il modo in cui si propone (anche se la mancanza di modelli di alias non era un problema prima di C++ 11) e il solito problema è la, ingombrare, macchinari pesanti modello di confusione e "brutto" codice boilerplate.

Affrontare questo problema, A. Alexandrescugave a presentation sull'argomento. Inizialmente c'è una piccola menzione delle esigenze di una tale tecnica:

enter image description here

Il proiettile che dice

  • Questa funzione è disponibile solo con i numeri

è reffering alle vostre tecniche e la necessità di disporre di condizionali temporali di compilazione per commutare l'esistenza di funzioni (interfaccia condizionale).

La discussione continua con una proposta per una nuova funzione lingua. Dal momento che tutti abbiamo inventato la ruota un paio di volte, lui dice, perché non una nuova sintassi del linguaggio, che ci permetterà di eseguire tali cose. Il suo joint work con H. Sutter, prodotto static if un toggler a tempo di compilazione che eliminerebbe il fabbisogno di soluzioni alternative come quello menzionato. Un semplice uso di questo sarebbe

template<int D> 
struct Vector 
{ 
    double coordinates[D]; 
    static if (D) { 
     double x() { return coordinates[0]; } 
    } 
    static if (D > 1) { 
     double y() { return coordinates[1]; } 
    } 
    static if (D > 2) { 
     double z() { return coordinates[2]; } 
    } 
}; 

OK forse non è l'uso più intelligente di esso, ma penso di comunicare l'idea.

Sul lato opposto ora, B. Stroustroup ha pubblicato un paper dove dopo aknowledging i problemi static if sta affrontando, spiega perché è un concetto imperfetto (gioco di parole :)) e la sua adozione sarebbe un disastro per la lingua (ahi!).

Questi erano i miei due centesimi, a giudicare dal livello dei partecipanti a questa "conversazione" mi piacerebbe avere qualche feedback su da che parte sono, o se fanno parte del processo di standardizzazione cosa voteranno per.

+1

Non conosco molta storia, ma forse è stato allora che Alexandrescu ha deciso di andare avanti e fare [il modo D] (http://dlang.org/cpptod.html#metatemplates) ... – iavr