Обходной путь C ++ для двойников в качестве параметров шаблона - PullRequest
0 голосов
/ 24 апреля 2018

Я знаю, что double не может быть параметрами шаблона, поэтому я ищу другой способ создания функции с несколькими параметрами. Мой текущий (явно неправильный) код выглядит так:

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 голосов
/ 24 апреля 2018

Поскольку мне не нужны параметры во время компиляции, я понял, что функтор - лучшее / правильное решение

В этом случае, если вы можете использовать C ++ 11, вы можете просто написать лямбду

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

Начиная с C ++ 14, вы можете упростить (ИМХО) следующее

#include <cmath>

int main ()
 {
   auto sellmeier = [B1=0.6961663,
                     B2=0.4079426,
                     B3=0.8974794,
                     C1=0.0684043*0.0684043,
                     C2=0.1162414*0.1162414,
                     C3=9.896161*9.896161] (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);
 }
0 голосов
/ 24 апреля 2018

Здесь вам нужен класс политики , который предоставит вашей функции требуемые значения (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 );
0 голосов
/ 24 апреля 2018

Есть ли способ создать функцию, которая принимает несколько параметров нецелого типа и один аргумент, не делая каждый параметр тоже аргументом?

Я не знаю, хорошая ли это идея, но ... да, я полагаю, вы можете заключить значения с плавающей запятой в static константу внутри struct.

Начиная с 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;
0 голосов
/ 24 апреля 2018

Поскольку мне не нужны параметры во время компиляции, я понял, что функтор - лучшее / правильное решение:

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);
0 голосов
/ 24 апреля 2018

В 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)

Хотя это становится очень недружественным для звонящего.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...