C++通过std::experimental::apply函数从元组获取参数包

C++ Getting parameter pack from tuple via std::experimental::apply function

我有以下关于 std::experimental::apply 的问题。据我了解,它需要函数对象和元组,然后将元组扩展为参数包,该参数包应用于给定的仿函数。不幸的是,当我尝试编译(函数调用)时,下面的代码出现类型不匹配问题。

        template<std::size_t population_size, std::size_t generations, typename Func,
            class Compare=std::greater<>,
            class Generator=std::default_random_engine,
            class Distribution=std::uniform_real_distribution<>>

                constexpr auto optimize(Func function, const std::pair<auto,auto>... range){ //CHECKING IF FUNCTION IS A FUNCTOR, TBD!

                    static_assert(sizeof...(range)>2, "Function needs at least two arguments");

                    //RANDOM NUMBER GENERATOR AND CHECKING ARITHMETIC TYPES
                    constexpr decltype(auto) generate_number=[&](std::pair<auto,auto> range){
                                static_assert(std::is_arithmetic<std::tuple_element_t<0, decltype(range)>>(),
                                        "First argument of std::pair has to be arithmetic!");
                                static_assert(std::is_arithmetic<std::tuple_element_t<1, decltype(range)>>(),
                                        "Second argument of std::pair has to be arithmetic!");
                                return std::bind(Distribution(range.first,range.second),Generator());
                    };

                    //SINGLE RANDOM INDIVIDUAL GENERATOR
                    decltype(auto) generate_random_individual=[&](){ //RUN THIS FUNCTION ASYNCHRONOUSLY, TBD!
                        auto genotype=std::make_tuple(generate_number(range)()...); //WORKS FINE


    //CRITICAL FUNCTION AND THE TOPIC OF THIS POST
                         auto key=std::experimental::apply(function,genotype);
    //CRITICAL FUNCTION AND THE TOPIC OF THIS POST

                        //return std::make_pair(key,genotype);
                    };
                    generate_random_individual();
}

这是我的测试用例(没有 experimental::apply 应该可以正常编译)。

#include<utility>
#include<iostream>
#include"optimalization.hpp"

class Function{
    public:
        Function()=default;
        double operator()(double x, double y, double z){
            return (std::exp(x+1.25)*std::pow(y,z))/std::exp((x*y)/z);
        }
};

int main(){
    Function f{};
    double x=optimize<100, 200>(f, std::make_pair(-21, 37), std::make_pair(22.5, 88.11), std::make_pair(-13, 37));
    std::cout << x << std::endl;

}

问题的核心是Function::operator()不是const。还有一些其他问题,例如 constexpr auto optimize(Func function, const std::pair<auto, auto>... range) 是无效的语法,但是一旦主要问题得到解决,这些问题基本上就会到位。

工作代码:

#include <cstddef>
#include <functional>
#include <random>
#include <experimental/tuple>
#include <type_traits>
#include <utility>

template<
    std::size_t population_size, std::size_t generations,
    typename Func,
    typename Compare = std::greater<>,
    typename Generator = std::default_random_engine,
    typename Distribution = std::uniform_real_distribution<>,
    typename... RangeElemT
>
auto optimize(Func function, std::pair<RangeElemT, RangeElemT> const... range) {
    static_assert(sizeof...(range) > 2, "Function needs at least two arguments");

    auto generate_number = [&](auto range) {
        static_assert(
            std::is_arithmetic<std::tuple_element_t<0, decltype(range)>>{},
            "First argument of std::pair has to be arithmetic!"
        );
        static_assert(
            std::is_arithmetic<std::tuple_element_t<1, decltype(range)>>{},
            "Second argument of std::pair has to be arithmetic!"
        );

        return std::bind(Distribution(range.first, range.second), Generator{});
    };

    auto genotype = std::make_tuple(generate_number(range)()...);
    auto key = std::experimental::apply(function, genotype);
    return std::make_pair(key, genotype);
}

#include <cmath>

struct Function {
    double operator ()(double x, double y, double z) const {
        return std::exp(x + 1.25) * std::pow(y, z) / std::exp(x * y / z);
    }
};

#include <iostream>
#include <boost/type_index.hpp>

int main() {
    namespace bti = boost::typeindex;

    Function f{};
    auto x = optimize<100, 200>(
        f,
        std::make_pair(-21, 37),
        std::make_pair(22.5, 88.11),
        std::make_pair(-13, 37)
    );
    std::cout
        << bti::type_id_with_cvr<decltype(x)>().pretty_name() << '\n'
        << x.first << " :: "
        << std::get<0>(x.second) << ", "
        << std::get<1>(x.second) << ", "
        << std::get<2>(x.second) << '\n';
}

Online Demo

另请注意,在您使用的两个地方 decltype(auto)auto 可以(并且为了清楚起见,应该)改用。