2009-08-30 14 views

cevap

11

Bu derler için optimize edilebilir. GCC'nin valarray sinüs hesaplamasını geciktirmek için ifade şablonlarını kullanması gibi görünüyor. Ancak bu, sin şablonunun dönüş türünü tam olarak valarray<T> değil, biraz garip karmaşık tipte yapar.

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

Düzenleme: GCC yapıyor gayet niçin bakınız AProgrammer standart alıntı.

Düzenleme: kesinlikle Standart yere uyum şekilde __typeof__ yapılmadan gerçekleştirilmesi Standart uyumlu geçici çözüm

biraz zordur. sin dönüş türünü almanız gerekir. Bunun için koşullu operatörü kullanabilirsiniz, Eric Niebler has shown. Gerçekte aramamış sin işlevine sahip olarak çalışır, ancak yalnızca yazılır.

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

: Diğer şube aynı tip koşullu operatör (aslında değerlendirilir bir) dönüştürmeye çalışırken, biz bir kukla parametresini üretebilir sadece fonksiyon kalem türünü anlamak mümkün Eğer adresi hemen almak istiyorsanız, work yazarak tekrar fp yazabilirsiniz.

template<typename T> 
T addy(T fp, id<T>) { return fp; } 

Şimdi, nihayet koşullu operatör hile kapsülleyen bir makro yazmak, ve bu tür bir matematik fonksiyonunun adresini almak istediğinizde kullanabilirsiniz.

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

adresini alıp daha sonra

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

I yapar Aynı anda MacGyver benzeri bir yeteneğiniz ile bu problemin çözümünde bir koşullu operatörün bükülme kabiliyetinden etkilendim ve bunu yapmak gerektiğini dehşete düşürdüm. :) –

+0

Vay canına, bunu anlamaya çalışmıyorum. ... –

+1

@robert, bazı pa varsa soru sormaya çekinmeyin anlamıyorsun. Onlar için bir açıklama yapmaya çalışacağım o zaman. Ayrıca eric nieblers 'operatörünün kullanımını kullanımını açıkladığınızdan emin olun: burada: http://www.artima.com/cppsource/foreach2.html –

4

Yaklaşık std::sin başlığında anlatılır, ama sonra ::sin atayın.

Çalışması gerekir. Not: <cmath> (standart dışı davranışlar da dahil) olsa bile, çoğu uygulama adın genel ad alanına enjekte edilmesine rağmen, sin tüm kullanımlarına hak kazanmanız gerektiğini unutmayın.

Düzeltme: maalesef şanssızsınız. Standart, sin(valarray<T> const &) hakkında aşağıdakileri bildirmektedir (26.3.3.3).

Bu fonksiyon, T türü sahip olan veya daha net bir şekilde gcc tarafından gerçekleştirilen

Optimizasyon standart tarafından verilen T. tip dönüştürülebilir ve böylece bir değer iade eder. Yukarıdaki kodun çalışması garanti edilmez.

+0

Ya GCC benim için çalışmıyor, bazı jenerik çalışması için aşağıdaki eserlerini iletin. Aynı hata mesajı :( –

+1

Haklısınız, GCC'de gerçekten başarısız olur. Yine de bir hata olduğunu söyleyebilirim. Standart açıkça 'şablon dönüştürülebilir valarray sin (const valarray &); valarray (*) '. – avakar

+0

Kabul ediyorum (const & valarray). bir GCC delilik gibi görünüyor :( –

10

26 3,1/3

bir valarray dönen her fonksiyon valarray arasında tüm sabit eleman fonksiyonları da, bu tür için geçerlidir, diğer bir tipteki bir nesneyi döndürmek için izin verilir.

amacı şablon ifadeleri (şirketinden elde edilen valarray < atama> yerine geçici bir yapı, diğer bir deyişle her kez hesaplama yaparak tüm dizi ile ilgili bir kez döngü) sonucu optimize etmek için kullanılabilir sağlamaktır.

z = sin(x+y); 

__typeof__ GCC kullanılarak

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

+1, o anlamda. xD –