Cette compile, en utilisant l'extension __typeof__
GCC. On dirait que le valarray
de GCC utilise des modèles d'expression pour retarder le calcul du sinus. Mais cela rendra le type de retour du modèle sin
pas exactement valarray<T>
, mais plutôt un type complexe bizarre.
#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: Voir AProgrammer pourquoi GCC est citation standard bien faire.
Edit: solution conforme à la norme
Faire cela sans __typeof__
d'une manière conforme strictement standard est un peu délicat. Vous devrez obtenir le type de retour sin
. Vous pouvez utiliser l'opérateur conditionnel pour cela, comme Eric Niebler has shown. Cela fonctionne en ayant la fonction sin
non appelée réellement, mais seulement vérifiée par type.En essayant de convertir l'autre branche (celle qui est en fait évalué) de l'opérateur conditionnel à ce même type, nous pouvons générer un paramètre fictif juste pour être en mesure de déduire le type de pointeur de fonction:
#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>())));
}
Si vous souhaitez obtenir l'adresse immédiatement, vous pouvez écrire work
pour qu'il renvoie à nouveau fp
.
template<typename T>
T addy(T fp, id<T>) { return fp; }
Maintenant, vous pouvez enfin écrire une macro pour résumer la supercherie de l'opérateur conditionnel, et l'utiliser quand vous voulez obtenir l'adresse d'une telle fonction mathématique.
#define DEDUCE(FN,Y) (1 ? ded_ty() : genFTy<Y>(FN(std::valarray<Y>())))
Pour obtenir l'adresse et le transmettre à une fonction générique, les œuvres suivantes, alors
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 Je suis simultanément impressionné par votre capacité de MacGyver à plier un opérateur conditionnel dans la solution à ce problème, et horrifié qu'il était nécessaire de le faire. :) –
wow, je ne comprends pas, je vais devoir étudier cette ... –
@robert, n'hésitez pas à poser des questions s'il y a quelques pa tu ne comprends pas. Je vais essayer de leur donner une explication à ce moment-là. Assurez-vous également de lire l'explication de eric nieblers sur son utilisation de 'operator?' Ici: http://www.artima.com/cppsource/foreach2.html –