Der Kern des Problems ist, dass Function::operator()
nicht const
ist. Es gibt einige andere Probleme, wie zum Beispiel constexpr auto optimize(Func function, const std::pair<auto, auto>... range)
, die ungültige Syntax ist, aber diese fallen im Grunde, sobald das Hauptproblem behoben ist.
Arbeitscode:
#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
Beachten Sie auch, dass Sie in beiden Orten verwendet decltype(auto)
, auto
(und aus Gründen der Klarheit sollte) stattdessen verwendet werden.
Korrigieren Sie die Formatierung Ihres Codes. –