使用不同类型

时间:2017-04-28 23:55:28

标签: c++ c++14

我试图建立一个基本但通用的渐变生成函数。目标是使函数gradient获取函数和可变参数,并在提供的点返回复数值的向量。代码如下:

grad.h

#include <complex>
#include <vector>
/**base case*/
template<typename FNC, typename T>
auto gradientHelper(FNC&& fnc, std::vector<T>&& val){
    return std::move(val);
}

/**recursive case*/
template<typename FNC, typename T,  typename...Ts>
auto gradientHelper(const FNC& fnc, std::vector<T>&& val, const T& current, const Ts&... others){
    val.emplace_back(fnc(std::complex<T>(current, 1.0), others...).imag());
    return gradientHelper(
        [&](const Ts&... others){
        return fnc(current, others...);
    }, std::move(val), others...);
}

/**calling case*/
template<typename FNC, typename T, typename...Ts>
auto gradient(FNC&& fnc, const T& param, const Ts&... params){
    return gradientHelper(fnc, std::vector<T>(), param, params...);
}

main.cpp

#include "grad.h"
#include <vector>
int main(){
    auto myTestFunc=[](const auto& x, const auto& y){
        return x*y;//gradient should be [y, x]
    };
    double testX=2;
    double testY=3;
    std::vector<double> answer({testY, testX});
    gradient(myTestFunc,  testX, testY);
}

使用g++ -std=c++14 -O3 main.cpp

进行编译

我收到以下错误:no known conversion for argument 1 from ‘std::complex<double>’ to ‘const double&’

我明白为什么会收到此错误。我已经使用参数类型gradient实例化了传递到complex, double的函数,然后使用参数类型double, complex再次调用它。我的问题是如何解决这个限制。我对变参数或SFINAE编码没有多少经验,而且我曾用过的资源并未指向正确的方向。任何帮助将不胜感激!

编辑:使代码没有依赖项,除了标准库。

Edit2:制作最小,完整且可验证的示例。

1 个答案:

答案 0 :(得分:0)

我通过更改代码解决了这个问题:

template<typename FNC, typename T,  typename...Ts>
auto gradientHelper(const FNC& fnc, std::vector<T>&& val, const T& current, const Ts&... others){
    val.emplace_back(fnc(std::complex<T>(current, 1.0), others...).imag());
    return gradientHelper(
        /*This won't work! The template is already defined!*/
        /*[&](const Ts&... others){
        return fnc(current, others...);*/

        /*This will work!  The remaining parameters 
          are deduced on the next call*/
        [&](const auto&... remaining){
           return fnc(current, remaining...);
        }
    }, std::move(val), others...);
}