這將編譯。看起來GCC的valarray
使用表達式模板來延遲竇的計算。但是這會使sin
模板的返回類型不完全是valarray<T>
,而是一些奇怪的複雜類型。
#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;
}
編輯:見AProgrammer的標準報價爲什麼GCC是罰款這樣做。
編輯:符合標準的解決方法
在嚴格符合標準的方式這樣做沒有__typeof__
是有點棘手。您將需要獲得返回類型sin
。您可以像這樣使用條件運算符,如Eric Niebler has shown。它的作用是讓sin
函數實際上不被調用,但只能進行類型檢查。通過嘗試另一個分支條件運算符來同類型的(這實際上是評估的一個)轉換,我們可以生成一個虛擬參數只是爲了能夠推斷出函數指針的類型:
#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>())));
}
如果您想立即獲取地址,則可以編寫work
,以便再次返回fp
。現在
template<typename T>
T addy(T fp, id<T>) { return fp; }
,你終於可以編寫一個宏來封裝有條件的經營者弄虛作假,當你想要得到任何這樣的數學函數的地址,使用它。
#define DEDUCE(FN,Y) (1 ? ded_ty() : genFTy<Y>(FN(std::valarray<Y>())))
要獲取地址,並將它傳遞給一些通用的功能,下面的作品,然後
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)));
我我同時對你的MacGyver式的能力印象深刻,這種能力可以讓一個條件操作符變成這個問題的解決方案,並且很震驚它有必要這樣做:) – 2009-08-30 14:24:33
哇,我不明白,我將不得不研究這個... – 2009-09-01 01:38:59
@robert,隨意提問,如果有一些pa rts你不明白。那麼我會試着給他們解釋一下。另外請務必閱讀eric nieblers對「運營商?」使用的解釋:http://www.artima.com/cppsource/foreach2.html – 2009-09-01 02:06:08