2015-07-10 87 views
1

事情要實現的是與在這個崗位相似:Select function name based on template parameter類型名稱的功能名稱映射在編譯時

交流庫,以處理不同的數值類型(浮動,雙,復-float,複雜的雙),會有不同名稱的功能。

當創建這樣一個c庫的包裝,我想找出一種方法來實現重載的效果,併爲所有數字類型使用相同的函數名稱。現在我用模板特:

#include <iostream> 

float saxpy(float x) { 
    return (1-x); 
} 

double daxpy(double x) { 
    return (1+x); 
} 

template <typename T> 
T axpy(T x); 

template<> 
inline float axpy<float>(float x) { 
    return saxpy(x); 
} 

template<> 
inline double axpy<double>(double x) { 
    return daxpy(x); 
} 


int main() { 

    auto z0 = axpy(1.0f); 
    auto z1 = axpy(1.0); 

    std::cout << z0 << " " << z1 << std::endl; 

    return 0; 
} 

有使用型特徵的另一種方式:

#include <type_traits> 
#include <iostream> 

float saxpy(float x) { 
    return (1-x); 
} 

double daxpy(double x) { 
    return (1+x); 
} 


struct saxpy_traits { 
    static float feval(float x) { return saxpy(x); } 
}; 

struct daxpy_traits { 
    static double feval(double x) { return daxpy(x); } 
}; 


template <typename T> 
struct axpy_traits { 
    typedef typename std::conditional<std::is_same<T, float>::value, saxpy_traits, daxpy_traits>::type Func; 
    inline static T feval(T x) { 
     return Func::feval(x); 
    } 
}; 

template<typename T> 
inline T axpy(T x) { 
    return axpy_traits<T>::feval(x); 
} 


int main() { 

    auto z0 = axpy(1.0f); 
    auto z1 = axpy(1.0); 

    std::cout << z0 << " " << z1 << std::endl; 

    return 0; 
} 

是否有更優雅的方式?謝謝。

+1

恐怕「有更優雅的方式嗎?」是廣泛的方式。你不喜歡你的方法是什麼? – user463035818

+1

兩個簡單的重載函數'float axpy(float);'和'double axpy(double);'? – MadScientist

+0

@ tobi303是「優雅」是含糊不清的。我期望的是,大部分代碼更短。這樣的代碼將是理想的,我知道這是不可能的。 template inline T axpy(T x){ \t return(T == float)? saxpy(x):daxpy(x); } – pem

回答

1

因爲我不知道究竟有資格成爲「優雅」,我提出了兩種備選方案:

float saxpy(float x) 
{ 
    return 1.0f - x; 
} 



double daxpy(double x) 
{ 
    return 1.0 + x; 
} 



namespace v1 { 

float axpy(float x) { return saxpy(x); } 

double axpy(double x) { return daxpy(x); } 

} // namespace v1 



namespace v2 { 

struct Axpy 
{ 
    float operator()(float x) const { return saxpy(x); } 

    double operator()(double x) const { return daxpy(x); } 
}; 

static constexpr Axpy axpy; 

} // namespace v2 

第一個版本只定義兩個重載函數。這與標準庫採取的方法類似,例如, std::sqrt

第二個版本定義了一個重載的operator()函數對象。此版本允許代碼爲

std::vector<float> fs { 1.f, 2.f, 3.f, 4.f }; 
    std::vector<float> rs(fs.size()); 
    std::transform(fs.begin(), fs.end(), rs.begin(), v2::axpy); 

它不能用第一個版本編譯。

+0

感謝您的回答。我認爲這兩個版本都比我的解決方案要好。實際上我正在使用BLAS/LAPACK。這是它的頭文件:https://github.com/xianyi/OpenBLAS/blob/develop/common_lapack.h – pem

相關問題