I have following question about std::experimental::apply. From what I understand it takes function object and tuple, and than expands the tuple into parameter pack, which is applied to given functor. Unluckily, I have type mismatch in the code below when I try to compile (function invocation).
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();
}
Here is my test case (should compile fine without 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;
}
The core of the problem is that Function::operator() is not const. There are some other issues, such as constexpr auto optimize(Func function, const std::pair<auto, auto>... range) being invalid syntax, but those basically fall into place once the main issue is fixed.
Working code:
#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
Also note that in both places you used decltype(auto), auto can (and for clarity, should) be used instead.
Related
I have two functions row and col. row is a wrapper for col and should pack the return types to a tuple.
Something like this
#include <iostream>
#include <tuple>
template<typename T>
T col(size_t i)
{
return T(i);
}
template<typename ...Ts>
auto row()
{
size_t i = 0;
return std::make_tuple(col<Ts>(i++)...); //<-- undefined behaviour
}
int main()
{
auto m_row = row<int,int,double>(); //should expand to std::make_tuple(col<int>(0),col<int>(1),col<double(2));
std::cout << "std::get<0>(m_row)-" << std::get<0>(m_row) << std::endl;
std::cout << "std::get<1>(m_row)-" << std::get<1>(m_row) << std::endl;
std::cout << "std::get<2>(m_row)-" << std::get<2>(m_row) << std::endl;
return 0;
}
My problem is the integer i which has to be incremented inside the expansion from 0 up to sizeof...(Ts). I have considered index of the current type but this is not working if the types are not unique. I lack of other ideas, any help would be appreciated.
Using std::index_sequence_for we can achieve a moderately simple (but not as simple as I had hoped) solution.
As #NathanOliver mentioned, it requires a level of indirection because we need to inform a helper function of the index sequence. The top level function now looks like this:
template <typename... Ts>
auto row() {
return make_row(std::tuple<Ts...>{},
std::index_sequence_for<Ts...>{});
}
So the helper function takes a default constructed tuple of the type requested, and the compile time sequence of integers.
All the helper needs to do now is to construct a Tuple using the index sequence (0, 1, ...).
template <typename Tuple, std::size_t... Is>
auto make_row(Tuple, std::index_sequence<Is...>) {
return Tuple{ Is... };
}
Finally, to verify this does what we wanted:
int main()
{
auto r = row<int,int,double>();
static_assert(std::is_same<decltype(r), std::tuple<int, int, double>>::value);
}
I am currently trying to teach myself variadic templates. However I am having trouble understanding anything past a simple adding template.
Currently I would want a template that would do the following:
Take any number of types
Takes parameters that requires the user to enter them in the following format:
T value, string descriptor
It then goes through each variable one by one, printing the descriptor before reading the variable
For example the output should look like this:
x (int) //this is the descriptor
//here something is being read into the variable x
y (int) //this is another descriptor
//something else is being read into y
.
.
.
Since its always the same operation, this should be possible. However my best try looked like this
template<typename t,typename... Args>
void generic_reader(t first,string desc,Args... args)
{
cout<<desc<<endl;
cin>>first;
generic_reader(args);
}
Obviously this doesnt work. However I cant think of another way of doing this. Again I have only started to work with variadic templates.
Can someone show me a solution with a detailed explanation?
Here's one way, using recursion.
#include <iostream>
// provide a terminating case
void generic_read()
{
}
// provide the general case which picks off the first 2 arguments
// and forwards the rest to another version of itself.
template<typename T, typename Printable, typename...Rest>
void generic_read(T& value ,Printable&& desc,Rest&&...rest)
{
std::cout << desc << std::endl;
std::cin >> value;
generic_read(std::forward<Rest>(rest)...);
}
// test
int main()
{
int x;
double y;
generic_read(x, "an integer:", y, "a double");
}
You're basically there -- you're just missing a base case. Also, you're missing the ... on your recursive call to generic_reader; it should be generic_reader(args...).
Here's some working code that does what you're trying to do:
#include <string>
#include <iostream>
void generic_reader()
{
std::cout << "no more stuff!" << std::endl;
}
template <typename T, typename... Args>
void generic_reader(T& first, const std::string& desc, Args&... args)
{
std::cout << desc << std::endl;
std::cin >> first;
std::cin.ignore(100, '\n');
generic_reader(args...);
}
int main()
{
int x, y, z;
generic_reader(x, "x", y, "y", z, "z");
std::cout << "x: " << x << " y: " << y << " z: " << z << std::endl;
return 0;
}
`
Walking through the code: your approach was correct, but there's no base case when you run out of arguments. On the second to last call, the remaining arguments are (z, "z"), which substitutes into the template successfully. But after that, there is a final call to generic_reader(), with no remaining arguments. You need to provide a candidate that can accept the final (empty) argument list.
One final note -- you'll notice that I passed in first by reference, so I could write to the original variables. If you do this, make sure that the remaining Args... is passed by reference as well! Otherwise, recursive calls will pass the remaining args by value, and calls after the first one will no longer reference the original variables.
It seems to me that you're using a sequence of std::pairs where the first type is fixed, std::string, and the second one is a variable type.
So you can write your function as
template <typename ... Args>
void generic_reader (std::pair<std::string, Args> & ... ps)
{ /* do something */}
and call it as
auto a = std::make_pair<std::string>("a", short(0));
auto b = std::make_pair<std::string>("b", 1);
auto c = std::make_pair<std::string>("c", 2L);
auto d = std::make_pair<std::string>("d", 3LL);
generic_reader(a, b, c, d);
Unfortunately I don't know (before c++17) how to use ps... in the body of the function so, in C++11 and in C++17, the best I can think is a solution based on recursion (as your original, with the recursion call corrected in generic_reader(args...);)
Starting from C++17 it's available a new (and more powerful) mode of use variadic arguments (look for "fold expression") and your function ca be simply written as
template <typename ... Args>
void generic_reader (std::pair<std::string, Args> & ... ps)
{ ( (std::cout << ps.first << std::endl, std::cin >> ps.second), ... ) ; }
The following is a full working C++17 example
#include <utility>
#include <iostream>
template <typename ... Args>
void generic_reader (std::pair<std::string, Args> & ... ps)
{ ( (std::cout << ps.first << std::endl, std::cin >> ps.second), ... ) ; }
template <typename ... Args>
void variadic_printer (Args & ... as)
{ ( (std::cout << as.first << ", " << as.second << std::endl), ... ) ; }
int main ()
{
auto a = std::make_pair<std::string>("a", short(0));
auto b = std::make_pair<std::string>("b", 1);
auto c = std::make_pair<std::string>("c", 2L);
auto d = std::make_pair<std::string>("d", 3LL);
generic_reader(a, b, c, d);
variadic_printer(a, b, c, d);
}
If you prefer not to use recursion you can always use this (c++14, but there exist implementations of index_sequence for c++11):
#include <utility>
#include <iostream>
#include <tuple>
template <class Tuple, std::size_t... Is>
void generic_reader_impl(std::index_sequence<Is...>, Tuple&& tuple) {
std::size_t dummy[] = { 0ul,
(static_cast<void>(std::cout << std::get<2ul*Is + 1ul>(tuple) << std::endl),
static_cast<void>(std::cin >> std::get<2ul*Is>(tuple)),
Is)...
};
static_cast<void>(dummy);
}
template <class... Args>
void generic_reader(Args&&... args) {
generic_reader_impl(std::make_index_sequence<sizeof...(Args) / 2>{}, std::forward_as_tuple(std::forward<Args>(args)...));
}
int main() {
int x;
double y;
generic_reader(x, "an integer:", y, "a double");
std::cout << x << std::endl;
std::cout << y << std::endl;
}
Output:
1
1.2
[live demo]
I found std::invoketo call every callable object with a set of parms and std::apply to expand a tuple as parms to a callable.
Is there a combination of both which enables to invoke any callable with a tuple as parms?
#include <iostream>
#include <tuple>
#include <functional>
class A
{
private:
int n;
public:
A( int _n ): n(_n){}
void operator()(int x, double y )
{
std::cout << n << " " << x << " " << y << std::endl;
}
void MemFun( int x, double y )
{
std::cout << n << " " << x << " " << y << std::endl;
}
};
int main()
{
A a(100);
std::invoke( a, 10, 1.23 );
auto parm2 = std::make_tuple( 1,2.34);
std::apply ( a, parm2 );
std::invoke ( &A::MemFun, a, 4, 5.67 );
// ???
std::??apply_invoke?? ( &A::MemFun, a, parm2 );
}
Do you mean something like this?
std::apply(&A::MemFun, std::tuple_cat(std::make_tuple(a), parm2));
Is there a combination of both which enables to invoke any callable with a tuple as parms?
std::apply can be used to invoke any callable, so I'm not really understanding the problem here. It's just like std::invoke for member functions: The first parameter needs to be the object you want to call the function on. Same goes for std::apply, where the first element of the passed tuple needs to be the object you want it to be called on.
If you don't like specifying std::tuple_cat and such, you can always create a wrapper:
template<typename F, typename T, typename U>
decltype(auto) apply_invoke(F&& func, T&& first, U&& tuple) {
return std::apply(std::forward<F>(func), std::tuple_cat(std::forward_as_tuple(std::forward<T>(first)), std::forward<U>(tuple)));
}
How about std::apply( std::bind(&A::MemFun, &a, std::placeholders::_1, std::placeholders::_2), parm2 );?
Edited to include suggestions and placeholders
How can I deduce the type or pair elements during compile-time? I need it to make a correct instantion accordingly to argument type (e.g. for Integer_random_generator those may be long, int, unsigned int etc., for real_random_generator double, float and other floating-points). I need to make generators with certain bounds as you can see in the commented out lines 63-77.
#ifndef OPTIMALIZATION_HPP
#define OPTIMALIZATION_HPP
#include<utility>
#include<random>
#include<experimental/random>
#include<functional>
#include<experimental/functional>
#include<experimental/tuple>
#include<algorithm>
#include<type_traits>
#include<iostream>
#include"tuple_for_each.hpp"
//ZNAJDZ/ZROB INDEKSOWANY DOSTEP DO TUPLI W CZASIE RUN-TIME'U
namespace numerics{
template<
std::size_t population_size, std::size_t generations,
typename Func,
typename Compare, //GREATER, LESS, TYPE RETURNED BY FUNCTION
typename Generator=std::default_random_engine,
template<typename>
typename RealDistribution=std::uniform_real_distribution,
template<typename>
typename IntegerDistribution=std::uniform_int_distribution,
typename ...Ts
>
auto optimize(
const Func& function, const Compare& comp,
const std::pair<Ts,Ts>&... range
){
std::size_t range_argument_count=sizeof...(range);
static_assert(range_argument_count>2,
"Function needs at least two range arguments"
);
//RANDOM NUMBER GENERATORS
auto real_random_generator=[&](const std::pair<auto,auto> range){
std::cout << "DOUBLE" << std::endl;
return std::bind(
RealDistribution<long double>(range.first,range.second),
//RealDistribution<decltype(range.first)>(range.first,range.second);
//HOW TO DEDUCE TYPE OF DISTRIBUTION FROM PAIR DURING COMPILE-TIME???
Generator()
);
};
auto integer_random_generator=[&](const std::pair<auto,auto>& range){
std::cout << "INTEGER" << std::endl;
return std::bind(
IntegerDistribution<long long>(range.first,range.second),
//IntegerDistribution<decltype(range.first)>(range.first,range.second);
//HOW TO DEDUCE TYPE OF DISTRIBUTION FROM PAIR DURING COMPILE-TIME???
Generator()
);
};
std::cout << integer_random_generator(std::get<0>(std::make_tuple(range...)))() << std::endl;
std::cout << real_random_generator(std::get<1>(std::make_tuple(range...)))()<<std::endl;
std::cout << integer_random_generator(std::get<2>(std::make_tuple(range...)))()<<std::endl;
//GENERATORS DEPENDING ON TYPE, USED THROUGH WHOLE PROGRAM
/*std::tuple<> generators;
numerics::for_each(std::make_tuple(range...), [&](std::pair<auto,auto>& x){ //FOR_EACH SPRAWDZENIA
try{
generators=std::tuple_cat(
generators,
std::make_tuple(integer_random_generator(x.first)));
}
catch(...){
generators=std::tuple_cat(
generators,
std::make_tuple(real_random_generator(x.first)));
}
}
);*/
return "pls work";
}
}
#endif
Test cases:
#include<utility>
#include<iostream>
#include"optimize.hpp"
class Function{
public:
Function()=default;
double operator()(int x, double y, long z)const{
return (std::exp(x+1.25)*std::pow(y,z))/std::exp((x*y)/z);
}
};
int main(){
Function f{};
auto comp=std::less<double>();
auto x=numerics::optimize<100, 200>(
f, comp,
std::make_pair(-21, 37),
std::make_pair(14.88, 88.41),
std::make_pair(-13, 37)
);
std::cout << x << std::endl;
}
Write a helper function to determine whether to make a real or an integer generator. In this case it will be based off the type of the first parameter in the range. I will leave it to you to determine how to also check the second parameter. (I haven't tested this code, but I am confident that the idea works).
template <class Range>
auto get_distribution(Range range, std::true_type)
{
return real_random_generator(range);
}
template <class Range>
auto get_distribution(Range range, std::false_type)
{
return integer_random_generator(range);
}
Simply use the pack expansion syntax to call your helper function on every range
auto generators = std::make_tuple(get_distribution(ranges,
std::is_floating_point<decltype(ranges.first)>{})...);
The std::is_floating_point is what determines which overload gets called for each range.
If you like tricky, but more concise, code you could try this out:
auto fs = std::make_tuple(integer_random_generator, real_random_generator);
auto generator = std::make_tuple(std::get<std::is_floating_point<decltype(ranges.first)>::value>(fs)(ranges)...);
Construct a tuple of your generator-generating lambdas (this wouldn't work if they weren't objects) and use the condition as an index into the tuple and immediately call it. I don't advocate using this, but I thought I would share it nonetheless.
I'd like to use std::make_pair usable with e.g. std::bind2nd so that I get an unary function object which I could use with e.g. std::transform.
Right now I'm using
template <typename T, typename U>
struct pair_creator : std::binary_function<T, U, std::pair<T, U> >
{
std::pair<T, U> operator()( T arg1, U arg2 ) const {
return std::make_pair( arg1, arg2 );
}
};
// ...
std::transform( start1, end2, start2, std::bind2nd( pair_creator<int, bool>(), true ) );
but I wonder - is there an easier way to make std::make_pair (or potentially any other binary function) usable with the binders except by writing little wrapper classes like pair_creator by hand?
I'd need a C++03 solution (for some obscure reason, stackoverflow always rewrites my c++0x tag to c++11 when saving the post...).
You need std::ptr_fun, which turns a plain function pointer into an adaptable binary function object (or a unary function object, if you pass it a one-arg function):
#include <functional>
#include <utility>
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
std::vector<int> intvec;
intvec.push_back(0);
intvec.push_back(1);
std::vector<std::pair<int,bool> > pairvec(intvec.size());
std::transform(
intvec.begin(),
intvec.end(),
pairvec.begin(),
// this is the significant line
std::bind2nd(std::ptr_fun(std::make_pair<int, bool>), true)
);
std::cout << pairvec[1].first << " " << pairvec[1].second << "\n";
}
ptr_fun is declared:
template <class Arg1, class Arg2, class Result>
pointer_to_binary_function<Arg1,Arg2,Result>
ptr_fun(Result (*)(Arg1,Arg2));
And for the unary version:
template <class Arg, class Result>
pointer_to_unary_function<Arg,Result>
ptr_fun(Result (*)(Arg));
Use lambda don't need to use bind adaptor.
std::vector<int> start1 = list_of(1)(2)(3)(4)(5);
std::vector<int> start2 = list_of(10)(20)(30)(40)(50);
std::vector<Pair> w_vecofpair; // vector of pair
w_vofpair.reserve(start1.size());
// create pair using lambda
std::transform( std::begin(start1), std::end(start1), std::begin(start2), // ranges
std::back_inserter(w_vecofpair), // result
[](int a,int b) { return std::make_pair(a,b);}); // pair creator
for (auto& pairInt : w_vecofpair)
{
std::cout << pairInt << "\n";
}
// bind 2nd arg to some value, say 2
std::transform( std::begin(start1), std::end(start1), std::begin(start2),
std::back_inserter(w_vecofpair), [](int a, int b) { return std::make_pair(a,2);});
for (auto& second : w_vecofpair | map_values)
{
std::cout << "The second value of our bind 2nd is: " << second << "\n";
assert(second==2);
}