C ++ шаблон неоднозначной реализации - PullRequest
1 голос
/ 23 февраля 2020

Я пытаюсь выполнить некоторую интерполяцию с использованием шаблонов, но получаю ошибку "неоднозначная реализация шаблона". Вот код

// interpolation rules
enum InterRule {trap, rect, trapSum};

// Rectangle rule
template <int n, int k, InterRule rule, class Expr> struct Integration {
    static double integrate(double a, double b){
        return (b-a)/n * Expr::eval(a + (k-1)*(b-a)/n) + Integration<n, k - 1, rule, Expr>::integrate(a,b);
    }
};

// termination case
template <int n, InterRule rule, class Expr> struct Integration<n,0,rule,Expr> {
    static double integrate(double a, double b){
        return 0;
    }
};

// Trapezoidal rule
template <int n, int k, class Expr> struct Integration<n, k, trap, Expr> {
    static double integrate(double a, double b){
        return (b-a)/n * (Expr::eval(a)/2 + Integration<n,k-1,trapSum,Expr>::integrate(a,b) + Expr::eval(b)/2);
    }
};

// Trapezoidal sum
template <int n, int k, class Expr> struct Integration<n, k, trapSum, Expr> {
    static double integrate(double a, double b){
        return Expr::eval(a + k*(b-a)/n) + Integration<n,k-1,trapSum,Expr>::integrate(a,b);
    }
};

По сути, я пытаюсь реализовать правило трапеции, чтобы оно статически разворачивалось. enter image description here Однако, похоже, что компилятор запутывается, использовать ли «случай завершения» или «трапециевидную сумму». Что я делаю не так и есть ли обходной путь? Я хочу заставить его использовать «случай завершения», если k==0 независимо от типа правила InterRule.

EDIT Дополнительный код для запуска :

// the types of expressions (+,-,*, etc.)
enum ExprType { mul, divide, add, sub, constant};

// constant
template <ExprType eType, class Left, class Right, int coeff, int power> struct Expr {
    static double eval(double x){
        return coeff * std::pow(x, power);
    }
};


int main()
{

    double a = 1;
    double b = 2;

    // Expr defines the function f(x) = x
    Integration<50, 50, trap, Expr<constant,int,int,1,1>> inte2;
    std::cout << inte2.integrate(a,b) << std::endl;

    return 0;
}

1 Ответ

1 голос
/ 23 февраля 2020

Вы можете попытаться устранить неоднозначность, добавив дополнительный параметр шаблона.

Может быть что-то вроде

// .................................................VVVVVVVVVVV
template <int n, int k, InterRule rule, class Expr, bool = true>
struct Integration {
   // ...
};

Наземный случай явно с false

template <int n, InterRule rule, class Expr>
struct Integration<n, 0, rule, Expr, false> { // <--- false !
    static double integrate(double a, double b){
        return 0;
    }
};

и добавление правильного параметра в рекурсивные вызовы

    return (b-a)/n * Expr::eval(a + (k-1)*(b-a)/n)
       + Integration<n, k - 1, rule, Expr, (k>1)>::integrate(a,b);
    // ....................................^^^^^

Ниже приведен полный пример компиляции

#include <cmath>
#include <iostream>

// interpolation rules
enum InterRule {trap, rect, trapSum};

// Rectangle rule
template <int n, int k, InterRule rule, class Expr, bool = true>
struct Integration {
    static double integrate(double a, double b){
        return (b-a)/n * Expr::eval(a + (k-1)*(b-a)/n)
           + Integration<n, k - 1, rule, Expr, (k>1)>::integrate(a,b);
    }
};

// termination case
template <int n, InterRule rule, class Expr>
struct Integration<n, 0, rule, Expr, false> {
    static double integrate(double a, double b){
        return 0;
    }
};

// Trapezoidal rule
template <int n, int k, class Expr>
struct Integration<n, k, trap, Expr> {
    static double integrate(double a, double b){
        return (b-a)/n * (Expr::eval(a)/2
           + Integration<n,k-1,trapSum,Expr,(k>1)>::integrate(a,b)
           + Expr::eval(b)/2);
    }
};

// Trapezoidal sum
template <int n, int k, class Expr>
struct Integration<n, k, trapSum, Expr> {
    static double integrate(double a, double b){
        return Expr::eval(a + k*(b-a)/n)
           + Integration<n,k-1,trapSum,Expr,(k>1)>::integrate(a,b);
    }
};

// the types of expressions (+,-,*, etc.)
enum ExprType { mul, divide, add, sub, constant};

// constant
template <ExprType eType, class Left, class Right, int coeff, int power> struct Expr {
    static double eval(double x){
        return coeff * std::pow(x, power);
    }
};


int main ()
 {

    double a = 1;
    double b = 2;

    // Expr defines the function f(x) = x
    Integration<50, 50, trap, Expr<constant,int,int,1,1>> inte2;
    std::cout << inte2.integrate(a,b) << std::endl;
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...