C ++ variadi c шаблон функции в std :: functions - PullRequest
0 голосов
/ 26 января 2020

В основном я хочу интегрировать многомерный интеграл с этой рекурсией.
Но сама проблема является общей. Это не указано c для интеграции.

#include "math.h"
#include <iostream>
#include <functional>

double f(double x,double y,double z){
    return x+y+z+1;
}

//Base
double redDim(std::function<double(double)> &f){
    return f(0); //a silly integrator for testing
}
// Recursion
template<typename Tfirst=double, typename... Trest>
auto redDim(std::function<double(Tfirst first,Trest... rest)> &f){
    return redDim([=](Trest... R){return redDim([=](double x){return f(x,R...);});});
}

int main(){
    std::cout<<redDim(f)<<std::endl;
    return 0;
}

Проблема в том, что компилятор говорит:

c:\C++\templateTutorial\templateTut.cpp: In function 'int main()':
c:\C++\templateTutorial\templateTut.cpp:24:19: error: no matching function for call to 'redDim(double (&)(double, double, double))'
     cout<<redDim(f)<<endl;
                   ^
c:\C++\templateTutorial\templateTut.cpp:12:8: note: candidate: 'double redDim(std::function<double(double)>&)'
 double redDim(std::function<double(double)> &f){
        ^~~~~~
c:\C++\templateTutorial\templateTut.cpp:12:8: note:   no known conversion for argument 1 from 'double(double, double, double)' to 'std::function<double(double)>&'
c:\C++\templateTutorial\templateTut.cpp:17:6: note: candidate: 'template<class Tfirst, class ... Trest> auto redDim(std::function<double(Tfirst, Trest ...)>&)'
 auto redDim(std::function<double(Tfirst first,Trest... rest)> &f){
      ^~~~~~
c:\C++\templateTutorial\templateTut.cpp:17:6: note:   template argument deduction/substitution failed:
c:\C++\templateTutorial\templateTut.cpp:24:19: note:   mismatched types 'std::function<double(Tfirst, Trest ...)>' and 'double(double, double, double)'
     cout<<redDim(f)<<endl;
                   ^
The terminal process terminated with exit code: 1

Так почему тип f не соответствует требованиям redDim()?
Таким образом, я могу ' даже не проверяйте, работает ли мой метод.
Надеюсь, вы мне поможете!

Ответы [ 2 ]

0 голосов
/ 27 января 2020

Исходя из ответа Яка - Адама Невраумона, должен скомпилироваться следующий код:

#include "math.h"
#include <iostream>
#include <functional>

double f(double x,double y,double z){
    return x+y+z+1;
}

//Base
double redDim(const std::function<double(double)> &f){
    return f(0); //a silly integrator for testing
}
// Recursion
template<typename Tfirst=double, typename... Trest>
auto redDim(const std::function<double(Tfirst first,Trest... rest)> &f) {

    return redDim(
    std::function<double(Trest...)>{
        [=](Trest... R)->double{return redDim([=](double x){return f(x,R...);});}});
}

template<class...Args>
auto redDim( double(*f)(Args...)) {
  return redDim( std::function<double(Args...)>{ f } );
}

int main(){
    std::cout<<redDim(f)<<std::endl;
    return 0;
}

Как уже указывал Якк, std::function и указатель на функцию не имеют одинаковый тип. Обратите внимание, что я также изменил тип аргумента redDim на const std::function<...> &). Вы также можете передать rvalue ссылки, используя синтаксис &&.

0 голосов
/ 26 января 2020

Указатель функции не является std::function.

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

Добавление шаблона redim( double(*f)(Args...) ) он вызывает функцию std one.

template<class...Args>
auto redDim( double(*f)(Args...) {
  return redDim( std::function<double(Args...)>{ f } );
}

и это должно работать.

Это может вывести сигнатуру указателя функции. Затем он явно преобразуется в std::function, который затем соответствует другим вашим redim функциям.

Вы должны явно преобразовать другие лямбды в std::function s:

// Recursion
template<typename Tfirst, typename... Trest>
auto redDim(std::function<double(Tfirst first,Trest... rest)> f){
  return redDim(
    std::function<double(Trest...)>{
      [=](Trest... R){
        return redDim(
          std::function<double(double)>{
            [=](double x){return f(x,R...);}
          }
        );
      }
    }
  );
}

Живой пример .

Также измените аргумент для последнего redDim на std::function<double(double)> (не ссылка). В качестве альтернативы, const&.

...