Questo compila, utilizzando l'estensione __typeof__
GCC. Sembra che GCC's valarray
utilizzi modelli di espressioni per ritardare il calcolo del seno. Ma questo renderà il tipo di ritorno del modello sin
non esattamente valarray<T>
, ma piuttosto un tipo strano e complesso.
#include <valarray>
template<typename T> struct id { typedef T type; };
int main() {
using std::valarray;
using std::sin;
id<__typeof__(sin(valarray<double>()))>::type (*fp)(const valarray<double> &) = sin;
}
Edit: citazione di serie Sede di AProgrammer del motivo per cui GCC è bene farlo.
Edit: standard compliant soluzione
Facendo questo senza __typeof__
in modo conforme rigorosamente standard è un po 'complicato. Dovrai ottenere il tipo di reso sin
. È possibile utilizzare l'operatore condizionale per questo, come Eric Niebler has shown. Funziona con la funzione sin
non effettivamente chiamata, ma solo con la verifica del tipo.Cercando di convertire l'altro ramo (quello che in realtà è valutata) dell'operatore condizionale per lo stesso tipo, possiamo generare un parametro fittizio solo essere in grado di dedurre la tipologia del puntatore funzione:
#include <valarray>
using std::valarray;
template<typename T> struct id {
typedef T type;
};
struct ded_ty {
template<typename T>
operator id<T>() { return id<T>(); }
};
template<typename E, typename T>
id<T(*)(valarray<E> const&)> genFTy(T t) {
return id<T(*)(valarray<E> const&)>();
}
template<typename T>
void work(T fp, id<T>) {
// T is the function pointer type, fp points
// to the math function.
}
int main() {
work(std::sin, 1 ? ded_ty() : genFTy<double>(std::sin(valarray<double>())));
}
Se si desidera ottenere l'indirizzo subito, è possibile scrivere work
in modo che restituisca nuovamente fp
.
template<typename T>
T addy(T fp, id<T>) { return fp; }
Ora, si può finalmente scrivere una macro per incapsulare l'inganno operatore condizionale, e usarlo quando si vuole ottenere l'indirizzo di tale funzione matematica.
#define DEDUCE(FN,Y) (1 ? ded_ty() : genFTy<Y>(FN(std::valarray<Y>())))
per ottenere l'indirizzo e passare a qualche funzione generica, le seguenti opere poi
std::transform(v1.begin(), v1.end(), v1.begin(),
addy(std::sin, DEDUCE(std::sin, double)));
std::transform(v2.begin(), v2.end(), v2.begin(),
addy(std::cos, DEDUCE(std::cos, double)));
I Sono contemporaneamente impressionato dalla tua abilità simile a MacGyver di piegare un operatore condizionale nella soluzione a questo problema, e sono rimasto sconvolto dal fatto che fosse necessario. :) –
wow, non capisco, ho intenzione di studiare questo ... –
@robert, sentiti libero di fare domande se ci sono alcuni pa non hai capito. Cercherò di dare una spiegazione per loro allora. Assicurati inoltre di leggere la spiegazione di eric nieblers del suo uso di 'operator?' Qui: http://www.artima.com/cppsource/foreach2.html –