2009-08-30 8 views
6

std :: sin(const valarray <double>&)はどのように参照するのですか?私はいくつかの<a href="http://www.cplusplus.com/reference/std/valarray/" rel="nofollow noreferrer">valarray</a>関数ポインタコードに問題抱えている

double (*fp)(double) = sin; 
valarray<double> (*fp)(const valarray<double> &) = sin; 

最初のコンパイルを、第二が与える:

error: no matches converting function 'sin' to type 'class std::valarray<double> (*)(const class std::valarray<double>&)' 

答えて

11

に最適化することができます。 GCCのvalarrayは、発現テンプレートを使用して洞の計算を遅らせるように見えます。しかし、それは正確にvalarray<T>ではなく、sinテンプレートの戻り値型を作るでしょうが、むしろいくつかの奇妙な複合型です。

#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; 
} 

編集:GCCはそれをやって罰金である理由のため参照AProgrammerの標準的な引用。

編集:規格に準拠し、回避策

__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; } 

さて、あなたは最終的に条件演算子の策略をカプセル化するマクロを書き、そしてあなたがそのような数学関数のアドレスを取得したいときにそれを使用することができます。それは、どちらかのGCCの上に私のために動作しません

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))); 
+1

私はあなたのMacGyverのような条件付き演算子をこの問題の解決法に曲げるような力に感心し、そうする必要があることを驚かせました:) –

+0

wow。私はこれを勉強しなければならない... –

+1

@robert、いくつかのPAがある場合は質問してくださいあなたは理解していません。私はそれらのための説明を次に与えることを試みる。また、ここで '演算子? 'の使用についてのeric nieblersの説明を読んでください:http://www.artima.com/cppsource/foreach2.html –

4

をあなたはタイトルにおよそstd::sinを話すが、その後::sinを割り当てます。

valarray<double> (*fp)(const valarray<double> &) = std::sin; 

これでうまくいくはずです。 <cmath>(非標準的な動作)を含める場合でも、大部分の実装でグローバル名前空間に名前が挿入されますが、すべての用途をsinに限定する必要があることに注意してください。

編集:残念ながら、あなたは運がありません。標準では、sin(valarray<T> const &)について次のとおりです(26.3.3.3)。

この関数は、型Tであるか、明確 は、GCCによって実行

最適化は、標準によって許可されているT.

型に変換することができる値を返します。上記のコードは動作することが保証されていません。

+0

、アドレスを取得し、いくつかの一般的な機能に渡し、以下ワークスが

#define DEDUCE(FN,Y) (1 ? ded_ty() : genFTy<Y>(FN(std::valarray<Y>()))) 

。同じエラーメッセージ:( –

+1

GCCで本当にうまくいかなかったのですが、バグだと思います。標準では、テンプレート valarray sin(const valarray &); valarrayの(*)(のconstのvalarray &) '。 – avakar

+0

私は同意するものとします。GCCの狂気のように見える:(私はそれを取り戻す –

10

26 3.1/3

のvalarrayを返す任意の関数がのvalarrayの 提供される全てのconstメンバ関数も、このタイプに適用可能であり、別の型のオブジェクトを返すことが許可されています。

目的は、テンプレート式は(直接得られたvalarray <に割り当てる>の代わりに一時的な建築物、すなわち各時間計算を行うアレイ全体に一度ループ)は、結果を最適化するために使用されることを可能にすることです。

z = sin(x+y); 

これは__typeof__ GCC拡張機能を使用して、コンパイル

for (i = 0; i < N; ++i) 
    z[i] = sin(x[i] + y[i]); 
+0

+1、理にかなっている。xDさん –

関連する問題

 関連する問題