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

时间:2016-06-13 01:08:24

标签: c++ tuples c++14 variadic-templates c++17

我有关于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();
}

这是我的测试用例(应该编译好没有实验:: 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;

}

1 个答案:

答案 0 :(得分:1)

问题的核心是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都可以(而且为了清楚起见)使用。