以 std::array 的双打作为参数或双打分别作为参数转换函数

Convert function with std::array of doubles as argument or the doubles separately as arguments

我想创建一个方法 convert,它采用通用函数 bar(可以是 std::functionlambdafunctor、.. .) 并将其转换为 std::function<double(std::array<double, 3>)>。函数 bar 可以是:

代码:

template<typename F>
std::function<double(std::array<double, 3>)> convert (F& bar)
{
    std::function<double(std::array<double,3>)> bar_converted = bar;
    return bar_converted;
}

代码:

template<typename F>
std::function<double(std::array<double, 3>)> convert(F& bar)
{
    std::function<double(std::array<double,3>)> bar_converted;
    auto array_bar = [bar]( std::array<double, 3> x)->double{ return bar(x[0], x[1], x[2]); };
    bar_converted = array_bar;
    return bar_converted;
}

问题是我不知道如何结合这两种 convert 方法,或者这是否可能?

正如 Max 所提到的,解决方案是使用 SFINAE 来检查可以调用哪些参数 F

#include <functional>
#include <type_traits>

/* Aliases to shorten the following code */
using BarArray = std::array<double, 3>;
using BarFunction = std::function<double(BarArray)>;

template <typename F>
/* Check whether F can be called with BarArray and returns double */
std::enable_if_t<std::is_same_v<std::result_of_t<F(BarArray)>, double>, BarFunction>
convert(F bar)
{
    return bar;
}

template<typename F>
/* Check whether F can be called with three doubles and returns double */
std::enable_if_t<std::is_same_v<std::result_of_t<F(double, double, double)>, double>, BarFunction>
convert(F bar)
{
    return [bar](BarArray x) {
        return bar(x[0], x[1], x[2]);
    };
}

我将从如何用 C++17 编写此代码开始:

template<typename F>
std::function<double(std::array<double, 3>)> convert(F&& f) // <== NB: forwarding ref
{
    if constexpr (std::is_invocable_v<F&, std::array<double, 3>) {
        // direct case
        return std::forward<F>(f);
    } else {
        // unpacking case
        return [f=std::forward<F>(f)](std::array<double, 3> arr) {
            return std::apply(f, arr);
        };
    }
}

在 C++14 中,您没有 if constexpris_invocable, or apply。第一个可以通过标记分派来实现(您可以使用 std::true_typestd::false_type 调用辅助函数),另外两个可以在 C++14 中很好地实现,并且是非常有用的辅助函数无论如何,您可能会需要很多其他功能。