2015-07-10 3 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

Смежные вопросы