很多非类型模板参数

时间:2017-09-17 17:21:43

标签: c++ c++11 c++14

我有一些非常重要的功能。它们非常通用,除了2个输入外,还依赖于大约12个参数。

这些参数是固定的,我有4或5组值(a1..a10)(b1..b10)等...我可以写几次这个函数但是为了效率和可维护性我想用非类型模板。

想象一下:

template <int a, int b, int c, int d, ..., int m>
double f(double x, double y) 
{ 
    return a*x+a*b*y+c+d+..+a*x*y; // some very complex math code
}

它仅用于以下N种方式:

f<1,2,3,...,6>(x,y)
f<4,5,6,...,60>(x,y)
f<10,20,....,50,60>(x,y)

(在该库的另一个应用程序中,参数集可能不同但仍然只有少数几个)

这很好,但不是很优雅......

我正在寻找一种“更好”的方式来以更清洁的方式对这些参数进行分组。

思路: - 创建许多充满constexpr [s]的PARAMS类型 - 一个抽象类,包含要重写的方法(不确定我是否可以将它与constexpr混合使用。)

我想知道是否还有一些其他更好的方式或者可用的东西可以很好地匹配我的问题。

编辑: 类似的东西是完美的! (显然这不起作用)。最重要的是我需要编译时评估。

#include <iostream>

struct Params1
{
    constexpr static int a = 2;
    constexpr static double b = 4;
    constexpr static int c = 6;
};

struct Params2
{
    constexpr static int a = 1;
    constexpr static double b = 4.3;
    constexpr static int c = 3;
};

template<P>
double f(double x)
{
    return x*P.a*P.b*P.c;
};


int main() {

    std::cout << f<Params1>(1.2) << std::endl;
    std::cout << f<Params2>(1.2) << std::endl;

    return 0;
}

3 个答案:

答案 0 :(得分:2)

不确定理解您的要求,但......

  

这些参数是固定的,我有4或5组值(a1..a10)(b1..b10)等。

我想您可以使用std::integer_sequence并定义4或5种类型

using set1 = std::integer_sequence<int, 1, 2, 3, ....>;
using set2 = std::integer_sequence<int, 2, 4, 6, ....>;
using set3 = std::integer_sequence<int, 10, 20, 30, ....>;
// ...

以这种方式定义函数

template <int a, int b, int c, int d, ..., int m>
double f (std::integer_sequence<int, a, ...> const &, double x, double y)
 { .. }

并按如下方式调用

f(set1{}, x, y);
f(set2{}, x, y);
f(set3{}, x, y);
// ...

以下是完整示例(但仅包含3个模板整数)

#include <utility>
#include <iostream>

using set1 = std::integer_sequence<int, 1, 2, 3>;
using set2 = std::integer_sequence<int, 2, 4, 6>;
using set3 = std::integer_sequence<int, 10, 20, 30>;

template <int a, int b, int c>
double f(std::integer_sequence<int, a, b, c> const &, double x, double y)
 { return a*(x+y)+b*(x-y)+c*(y-x); }

int main ()
 {
   double x { 1.0 };
   double y { 2.0 };

   std::cout << f(set1{}, x, y) << std::endl; // print 4
   std::cout << f(set2{}, x, y) << std::endl; // print 8
   std::cout << f(set3{}, x, y) << std::endl; // print 40
 }

答案 1 :(得分:2)

重写f()如下,最后一个(发布“编辑”)示例应该有效

template <typename P>
double f(double x)
{
    return x * P::a * P::b * P::c;
}

要点

(a)使用template <P>

更改template <typename P>

(b)并使用P::aP::bP::c类型中的静态值)代替P.a,{{1 }和P.b(对象的值)

答案 2 :(得分:1)

您给出的示例代码可以很好地进行一些细微的更改。也许这就是你要找的东西?

struct Params1
{   
    constexpr static int a = 2;
    constexpr static double b = 4;
    constexpr static int c = 6;
};  

struct Params2
{   
    constexpr static int a = 2;
    constexpr static double b = 4;
    constexpr static int c = 6;
};  

template<typename P>
double f(double x)
{   
    return x*P::a*P::b*P::c;
}   


int main() {

    std::cout << f<Params1>(1.2) << std::endl;
    std::cout << f<Params2>(1.2) << std::endl;

    return 0;
}