用于模板参数的双精度C ++解决方法

时间:2018-04-24 15:51:00

标签: c++ templates

我知道双打不能成为模板参数,因此我正在寻找另一种方法来创建具有多个参数的函数。我当前(显然是错误的)代码如下所示:

template<double B1, double B2, double B3, double C1, double C2, double C3>
    double sellmeier(const double wavelength) {
        double refractive_index_sq = 1;
        double lambda_sq = std::pow(wavelength, 2);
        refractive_index_sq += B1*lambda_sq/(lambda_sq-C1);
        refractive_index_sq += B2*lambda_sq/(lambda_sq-C2);
        refractive_index_sq += B3*lambda_sq/(lambda_sq-C3);
        return refractive_index_sq;
    }

有没有办法创建一个函数,它接受几个非整数类型参数和一个参数而不会使每个参数都成为一个参数?

5 个答案:

答案 0 :(得分:2)

您想要的是策略类,它将为您的函数提供所需的值(SpecificConstants)。

struct SpecificConstants
{
    static constexpr double b1 { 0.6961663 };
    static constexpr double b2 { 0.4079426 };
    static constexpr double b3 { 0.8974794 };
    static constexpr double c1 { 0.0684043 * 0.0684043 };
    static constexpr double c2 { 0.1162414 * 0.1162414 };
    static constexpr double c3 { 9.896161 * 9.896161 };
};

您的功能只需要此政策类(Constants

template< typename Constants >
double sellmeier( const double wavelength )
{
    double refractive_index_sq = 1;
    double lambda_sq           = std::pow( wavelength, 2 );
    refractive_index_sq += Constants::b1 * lambda_sq / ( lambda_sq - Constants::c1 );
    refractive_index_sq += Constants::b2 * lambda_sq / ( lambda_sq - Constants::c2 );
    refractive_index_sq += Constants::b3 * lambda_sq / ( lambda_sq - Constants::c3 );
    return refractive_index_sq;
}

然后,可以像这样调用函数:

sellmeier< SpecificConstants >( 2.0 );

答案 1 :(得分:1)

在c ++ 14中,您可以执行以下操作,为了简洁起见,使用一个参数显示:

constexpr double GetB1(int b1Index)
{
    switch (b1Index)
    {
        case 0: return 1.2345;
        case 1: return 2.3456;
        default: return 3.4567;
    }
}

template<int B1Index>
    double obviouslyNotSellmeier(const double wavelength) {
        return wavelength * GetB1(B1Index);
    }

obviouslyNotSellmeier<1>(0.123)

虽然对来电者非常不友好。

答案 2 :(得分:1)

  

有没有办法创建一个函数,它接受几个非整数类型参数和一个参数而不会使每个参数都成为一个参数?

我不知道这是不是一个好主意但是......是的,我想你可以将你的浮点数值static保持在struct&#39;第

从C ++ 11(constexpr)开始,您只需定义

即可
struct X1 { static constexpr double value { 1.2 }; };
struct X2 { static constexpr double value { 2.3 }; };
struct X3 { static constexpr double value { 3.4 }; };
struct Y1 { static constexpr double value { 4.5 }; };
struct Y2 { static constexpr double value { 5.6 }; };
struct Y3 { static constexpr double value { 6.7 }; };

将它们作为模板参数传递给sellmeier()

sellmeier<X1, X2, X3, Y1, Y2, Y3>(1.0);

并使用value

中的sellmeier()类型
template <typename B1, typename B2, typename B3,
          typename C1, typename C2, typename C3>
double sellmeier (const double wavelength)
 {
   double refractive_index_sq = 1;
   double lambda_sq = std::pow(wavelength, 2);
   refractive_index_sq += B1::value*lambda_sq/(lambda_sq-C1::value);
   refractive_index_sq += B2::value*lambda_sq/(lambda_sq-C2::value);
   refractive_index_sq += B3::value*lambda_sq/(lambda_sq-C3::value);
   return refractive_index_sq;
 }

在C ++ 11之前(没有constexpr可用)定义包装结构的语法有点烦人:你必须初始化结构体外的const

struct X1 { static double const value; };
struct X2 { static double const value; };
struct X3 { static double const value; };
struct Y1 { static double const value; };
struct Y2 { static double const value; };
struct Y3 { static double const value; };

double const X1::value = 1.2;
double const X2::value = 2.3;
double const X3::value = 3.4;
double const Y1::value = 4.5;
double const Y2::value = 5.6;
double const Y3::value = 6.7;

答案 3 :(得分:0)

由于我在编译时不需要参数,因此我意识到仿函数是更好/正确的解决方案:

struct sellmeier {
    sellmeier(double B1, double B2, double B3, double C1, double C2, double C3) :
            B1(B1), B2(B2), B3(B3), C1(C1), C2(C2), C3(C3) {}
        double operator()(const double wavelength) {
            double refractive_index_sq = 1;
            double lambda_sq = std::pow(wavelength, 2);
            refractive_index_sq += B1 * lambda_sq / (lambda_sq - C1);
            refractive_index_sq += B2 * lambda_sq / (lambda_sq - C2);
            refractive_index_sq += B3 * lambda_sq / (lambda_sq - C3);
            return refractive_index_sq;
        }
    private:
        double B1, B2, B3, C1, C2, C3;
};

//functor with sellmeier coefficients for fused quartz
auto sellmeier_fused_quartz = sellmeier(0.6961663, 0.4079426, 0.8974794, 0.0684043*0.0684043, 0.1162414*0.1162414, 9.896161*9.896161);

答案 4 :(得分:0)

  

由于我在编译时不需要参数,我意识到仿函数是更好/正确的解决方案

在这种情况下,如果你可以使用C ++ 11,你可以简单地写一个lambda

  SqlConection con=new SqlConnection("connection string here")
  SqlCommand cmd = new SqlCommand("Select * from table",con)
  SqlDatareader dr = cmd.ExecuteReader();
  While (dr.Read())
   {
    MyDatarow row = new MyDatarow;
    If (row.ItemHolder.ColumnDefinition.Count = 0)
     {
       row.ItemHolder.ColumnDefinition.Add(new ColumnDefinition)//this will ad required number of columns which will represent the cells
     }     
    TextBox txtbx = new TextBox;
    txtbx.Height = 20
    row.ItemHolder.Children.Add(txtbx)
    Grid.SetColumn(txtbx,1) /// here 1 is the column count, change it as you want :)
    MyDatagrid.Childer.Add(row);
    MyDatagrid.height = MyDatagrid.height + 30 ;
   }

从C ++ 14开始,你可以简化(恕我直言)如下

#include <cmath>

int main ()
 {
   auto B1=0.6961663;
   auto B2=0.4079426;
   auto B3=0.8974794;
   auto C1=0.0684043*0.0684043;
   auto C2=0.1162414*0.1162414;
   auto C3=9.896161*9.896161;

   auto sellmeier = [=] (double const wavelength)
    {
      double refractive_index_sq = 1;
      double lambda_sq = std::pow(wavelength, 2);
      refractive_index_sq += B1*lambda_sq/(lambda_sq-C1);
      refractive_index_sq += B2*lambda_sq/(lambda_sq-C2);
      refractive_index_sq += B3*lambda_sq/(lambda_sq-C3);
      return refractive_index_sq;
    };

   sellmeier(1.0);
 }