kompiluje to, używając rozszerzenia __typeof__
GCC. Wygląda na to, że GCC ma valarray
używa szablonów ekspresji do opóźnienia obliczenia zatoki. Ale to sprawi, że typ zwrotu szablonu sin
nie będzie dokładnie taki jak valarray<T>
, ale raczej jakiś dziwny typ złożony.
#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: standard cytat Zobacz AProgrammer za dlaczego GCC jest w porządku robić.
Edit: Standardowy obejście zgodny
Robi to bez __typeof__
w ściśle zgodny ze standardem sposób jest nieco skomplikowane. Będziesz musiał uzyskać typ zwrotu sin
. Możesz użyć do tego operatora warunkowego, jak Eric Niebler has shown. Działa, ponieważ funkcja sin
nie jest wywoływana, ale tylko sprawdzana.Próbując przekształcić drugą gałąź (ten, który jest faktycznie analizowany) operatora warunkowego do tego samego typu, możemy wygenerować manekina parametr, tylko żeby być w stanie wydedukować rodzaj wskaźnika funkcję:
#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>())));
}
Jeśli chcesz od razu uzyskać adres, możesz napisać work
, aby ponownie zwrócić fp
.
template<typename T>
T addy(T fp, id<T>) { return fp; }
Teraz można wreszcie napisać makro do hermetyzacji Operator warunkowy oszustwa i używać go, gdy chcemy uzyskać adres takiej funkcji matematycznej.
#define DEDUCE(FN,Y) (1 ? ded_ty() : genFTy<Y>(FN(std::valarray<Y>())))
Aby uzyskać adres i przekazać go do jakiegoś rodzajowego funkcji, następujące prace następnie
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)));
Jestem jednocześnie pod wrażeniem Twojej zdolności MacGyvera do zginania operatora warunkowego w rozwiązaniu tego problemu i przeraziłem się, że było to konieczne. :) –
wow. Nie rozumiem. Będę musiał to przestudiować ... –
@robert, możesz zadawać pytania, jeśli są jakieś rts, których nie rozumiesz. Postaram się wtedy wytłumaczyć im. Należy również przeczytać wyjaśnienie eric ávlersów dotyczące jego użycia 'operatora?' Tutaj: http://www.artima.com/cppsource/foreach2.html –