Related
I'm sorry for the weird title. I don't know how to word this.
If I have function func()
How do I do this:
func(func(func(func(func(x)))))
where it repeats N times?
I'm trying to implement Conway's Game of Life. I have a function that takes a vector and outputs another vector, which is the next generation of the input vector. So generation 3's vector would be func(func(func(x))).
The easy way, simply using for loop:
int x = some_initial_value;
for (int i = 0; i < NUMBER_OF_ITERATIONS; ++i)
{
x = func(x);
}
While the 'easy way' works in most cases, I'd like to provide you a way to do in in cases where return type (for a given argument type) might differ from argument type:
template<size_t i, typename F, typename Arg>
auto times(F f, const Arg& arg) {
if constexpr (i == 0) {
return arg;
} else {
return times<i - 1>(f, f(arg));
}
}
// usage: times<5>(func, x);
I have a function of a class I would like to iteratively call inside a loop, and while the loop is fixed, I want to be able to provide different functions (from the given object). To approach this, I created a templated struct MyWrapper to take the object whose function I want to call, the function itself, and data for which to evaluate the function. (In that sense, the member function will always have the same signature)
What I found though, was that using a member function pointer incurs a huge performance cost, even though at compile time, I know the function I want to call. So I was messing around to try and fix this, and (while I'm still unclear why the first situation happens), I've experienced another interesting behaviour.
In the following situation, every call to the wrapper function MyWrapper::eval will actually attempt to copy my whole Grid object into the parameter to the given function it has to wrap, f, even though the call to MyEquation::eval will know not to copy it every time (because of optimization).
template<typename T>
double neighbour_average(T *v, int n)
{
return v[-n] + v[n] - 2 * v[0];
}
template<typename T>
struct MyEquation
{
T constant;
int n;
T eval(Grid<T, 2> v, int i)
{
return rand() / RAND_MAX + neighbour_average(v.values + i, n) + constant;
}
};
template<typename T, typename R, typename A>
struct MyWrapper
{
MyWrapper(T &t, R(T::*f)(A, int), A a) : t{ t }, f{ f }, a{ a } {}
auto eval(int i)
{
return (t.*f)(a, i);
}
protected:
A a;
T &t;
R(T::*f)(A, int);
};
int main(int argc, char *argv[])
{
srand((unsigned int)time(NULL));
for (iter_type i = 0; i < config().len_; ++i)
{
op.values[i] = rand() / RAND_MAX;
}
srand((unsigned int)time(NULL));
double constant = rand() / RAND_MAX;
int n = 2;
int test_len = 100'000,
int test_run = 100'000'000;
Grid<double, 2> arr(100, 1000);
MyEquation<double> eq{ constant, n };
MyWrapper weq(eq, &MyEquation<double>::eval, arr); // I'm wrapping what I want to do
{
// Time t0("wrapper thing");
for (int i = 0; i < test_run; ++i)
{
arr.values[n + i % (test_len - n)] += weq.eval(n + i % (test_len - n)); // a call to the wrapping class to evaluate
}
}
{
// Time t0("regular thing");
for (int i = 0; i < test_run; ++i)
{
arr.values[n + i % (test_len - n)] += rand() / RAND_MAX + neighbour_average(arr.values + n + i % (test_len - n), n) + constant; // a usage of the neighbour function without the wrapping call
}
}
{
// Time t0("function thing");
for (int i = 0; i < test_run; ++i)
{
arr.values[n + i % (test_len - n)] += eq.eval(arr, n + i % (test_len - n)); // raw evaluation of my equation
}
}
}
Some context:
Grid is just a glorified dynamic array Grid::values with a few helper functions.
I've retained some of the (seemingly unnecessary) templates to my function and object, because it closely parallels how my code is actually set up.
The Time class will give me the duration of the object lifetime, so its a quick and dirty way of measuring certain blocks of code.
So anyways...
If the following code is changed so the signature of the function taken by MyWrapper is R(T::*f)(A&, int), then the execution time of MyWrapper::eval will be almost identical to the other calls (which is what I want anyways).
Why doesn't the compiler (msvc 2017) know it should treat the call weq.eval(n) (and consequently (t.*f)(a, n)) the with the same optimization considerations way as the direct evaluation, if the signature and function is given at compile time?
A function parameter is its own variable, which gets initialized from a function call argument. So when a function argument in the calling function is an lvalue such as the name of an object previously defined, and the function parameter is an object type, not a reference type, the parameter and the argument are two different objects. If the parameter has a class type, this means a constructor for that type has to be executed (unless the initialization is an aggregate initialization from a {} initializer list).
In other words, every call to
T eval(Grid<T, 2> v, int i);
needs to create a new Grid<T, 2> object called v, whether it's called via function pointer or by the member name eval.
But in many cases, initialization of a reference doesn't create a new object. It appears your eval doesn't need to modify v or the MyEquation, so it would be better to declare that eval as:
T eval(const Grid<T, 2> &v, int i) const;
This would mean the function pointer in Wrapper needs to be R (T::*f)(const A&, int) const.
But another change you might want to make, especially since Wrapper is already a template: Just make the function used a generic type, so that it can hold non-member function pointers, wrappers to member function pointers with any signature, lambdas, or any other class type with an operator() member.
#include <utility>
template<typename F, typename A>
struct MyWrapper
{
MyWrapper(F f, A a) : f{ std::move(f) }, a{ std::move(a) } {}
auto eval(int i)
{
return f(a, i);
}
protected:
A a;
F f;
};
Then two ways to create your Wrapper weq; are:
Wrapper weq([&eq](const auto &arr, int i) {
return eq.eval(arr, i);
}, arr);
or (requires #include <functional>):
using namespace std::placeholders;
Wrapper weq(
std::bind(std::mem_fn(&MyEquation<double>::eval), _1, _2),
arr);
auto dothings = [](long position) {
auto variable;
/*do things*/
return variable;
};
float x = dothings(1l);
char y = dothings(2l);
Basically, the thing I'm curious about, is whether is it possible in any way for the variable inside the lambda to deduce the type the return value is assigned to, in this situation it's float and char. Is there an equivalent to template typename? Thanks.
This can be done, but it's a) kinda complex, and b), not really a great idea, 99.9% of the time. Here's how you proceed. The only way you can do something based on the type you assign the expression to is to take advantage of implicit conversions. This requires a templated implicit conversation operator, which can't be declared locally in a lambda, so we have to start by writing a bit of support code:
template <class T>
struct identity {
T get(); // not defined
};
template <class F>
struct ReturnConverter {
F f;
template <class T>
operator T() {
return f(identity<T>{});
}
};
template <class F>
auto makeReturnConverter(F f) { return ReturnConverter<F>{f}; }
The first class is just to help the lambda with inferring types. The second class is one that itself takes a lambda (or any callable), and has an implicit conversion operator to any type. When the conversion is asked for, it calls the callable, using our identity class template as a way to feed the type. We can use this now like this:
auto doIt = [] (long l) {
return makeReturnConverter([=] (auto t) {
return l + sizeof(decltype(t.get()));
});
};
This lambda creates our special ReturnConverter class by feeding in another lambda. This lambda captures the long l argument of the outer lambda (by value), and it's prepared to accept our special identity class as the sole argument. It can then back out the "target" or destination type. I use sizeof here to quickly show an example where the result depends on both the argument to the lambda, and the target type. But note that once I get the type using decltype(t.get()), I could actually declare a variable of that type and do whatever I wanted with it.
float x = doIt(5);
double y = doIt(2);
After these calls, x will be 9 (a float is size 4, + 5) and y will be 10 (double is size 8, + 2).
Here's a more interesting example:
auto doIt2 = [] (long l) {
return makeReturnConverter([=] (auto t) {
decltype(t.get()) x;
for (std::size_t i = 0; i != l; ++i ) {
x.push_back(i*i);
}
return x;
});
};
std::vector<int> x = doIt2(5);
std::deque<int> y = doIt2(5);
Here, I'm able to generically build a standard container according to what the left side asks for, as long as the standard container has the push_back method.
Like I said to start, this is overly complicated and hard to justify in the vast majority of cases. Usually you could just specific type as an explicit (non-inferred) template parameter and auto the left. I have used it in very specific cases though. For instance, in gtest, when you declare test fixtures, any reused data are declared as member variables in the fixture. Non static member variables have to be declared with their type (can't use auto), so I used this trick to allow quickly building certain kinds of fixture data while keeping repetition to as close to zero as I could. It's ok in this use case because that code that code doesn't need to be very robust but really wants to minimize repetition at almost any cost; usually this isn't such a good trade-off (and with auto available on the left isn't usually necessary).
The answer here is NO.
The type returned is based on the values used inside the function
auto dothings = [](long position) {
auto variable; // This is illegal as the compiler can not deduce the type.
// An auto declaration needs some way for it to determine the type.
// So that when you use it below it can determine the
// return type of the function.
/*do things*/
return variable;
};
The assignment operator looks at the type of the result expression to see if there are any auto conversions that can be applied to convert the function result type into the destination of the assignment type.
char x = dothings(10); // the result of the expression on the right
// is converted to char before assignment. If
// it can't be converted then it is a compiler error.
You can think of lambdas as syntactic sugar for creating a functor.
[<capture List>](<Parameter List>) {
<Code>
}
Is the same as:
struct <CompilerGeneratedName>
{
<Capture List With Types>;
Constructor(<Capture List>)
: <Capture List With Types>(<Capture List>)
{}
<Calculated Return> operator()(<Parameter List>) const {
<Code>
}
}{<Capture List>};
Example:
{
int y = 4;
auto l1 = [&y](int x){return y++ + x;}
struct MyF
{
int& y;
MyF(int& y)
: y(y)
{}
int operator()(int x) const {
return y++ + x;
}
};
auto l2 = MyF(y);
std::cout << l2(5) << " " << l1(5) << "\n";
}
The only way I know to do this is to use a template parameter:
template<typename T>
T dothings(long value)
{
T result;
...
return result;
}
auto x = dothings<float>(1l);
auto y = dothings<char>(2l);
The template also allows you to specialize for certain types. So if you wanted different logic for doubles, you could write the following:
template<>
double dothings<double>(long value)
{
T result;
...
return result * 2.0;
}
Suppose I have a lambda that does something:
auto thing = [](int x){ /* Stuff */ };
I want to save off the value "x" and call it later so I do:
auto other = boost::hana::partial(thing, 42);
Now, because I want to do some type erasure on this I want to take the address of the operator().....so I try to do this:
using type = decltype(other);
void (type::*ptr)(void) = &type::operator();
Clang complains, that the other object does not a sufficient function that matches the requirements: godbolt
It appears that the partial type is returning a reference (to void?)......why does this not work?
It (the operator()) has & const& && etc overloads; your member function pointer does not qualify *this by const or r/l value-ness. So does not match.
Add & or const& or && or const&& before = on the line that fails to compile, and it will compile.
Here is a [MCVE]:
struct foo {
void bar()&{}
};
int main(){
auto p = &foo::bar;
void(foo::*p2)() = p; // lacks &
}
I want to implement a math parser with user-defined function.
There are several problems to be solved.
For example, int eg(int a,int b){return a+b;} is the function I want to add to the parser.
First: How to store all the functions into a container?
std::map<std::string,boost::any> func_map may be a choose (by func_map["eg"]=eg". However, It's very hard to call the function in this kind of map, for I have to use any_cast<T> to get the real function from the wrapper of boost::any.
Second: How to handle the overloaded function?
It's true that I can distinguish the overloaded functions by the method of typeid, but it's far from a real implementation.
Parsering expressions is not a difficult skill and the hardest part is described above.
muparserx provides an interesting solution for this problem, but I'm finding another method.
I'm not familiar with lambda expressions but may be it's an acceptable way.
Update:
I need something like this:
int eg(int a,int b){ return a+b;}
int eg(int a,int b, string c){return a+b+c.length();}
double eh(string a){return length.size()/double(2);}
int main(){
multimap<string,PACKED_FUNC> func_map;
func_map.insert(make_pair("eg",pack_function<int,int>(eg));
func_map.insert(make_pair("eg",pack_function<int,int,string>(eg));
func_map.insert(make_pair("eh",pack_function<string>(eh));
auto p1=make_tuple(1,2);
int result1=apply("eg",PACK_TUPLE(p1));//result1=3
auto p2=tuple_cat(p1,make_tuple("test"));
int result2=apply("eg",PACK_TUPLE(p2));//result2=7
auto p3=make_tuple("testagain");
double result3=apply("eh",PACK_TUPLE(p3));//result3=4.5
return 0;
}
How to store all the functions into a container?
To store then inside some container, they must be of the same type. The std::function wrapper is a good choice, since this allows you to use even stateful function objects. Since you probably don't want all functions to take the same number of arguments, you need to "extract" the arity of the functions from the static host type system. An easy solution is to use functions that accept a std::vector:
// Arguments type to the function "interface"
using Arguments = std::vector<int> const &;
// the interface
using Function = std::function<int (Arguments)>;
But you don't want your users to write functions that have to unpack their arguments manually, so it's sensible to automate that.
// Base case of packing a function.
// If it's taking a vector and no more
// arguments, then there's nothing left to
// pack.
template<
std::size_t N,
typename Fn>
Function pack(Fn && fn) {
return
[fn = std::forward<decltype(fn)>(fn)]
(Arguments arguments)
{
if (N != arguments.size()) {
throw
std::string{"wrong number of arguments, expected "} +
std::to_string(N) +
std::string{" but got "} +
std::to_string(arguments.size());
}
return fn(arguments);
};
}
The above code handles the easy case: A function that already accepts a vector. For all other functions they need to be wrapped and packed into a newly created function. Doing this one argument a time makes this relatively easy:
// pack a function to a function that takes
// it's arguments from a vector, one argument after
// the other.
template<
std::size_t N,
typename Arg,
typename... Args,
typename Fn>
Function pack(Fn && fn) {
return pack<N+1, Args...>(
[fn = std::forward<decltype(fn)>(fn)]
(Arguments arguments, Args const &... args)
{
return fn(
arguments,
arguments[N],
args...);
});
}
The above only works with (special) functions that already take a vector. For normal functions we need an function to turn them into such special functions:
// transform a function into one that takes its
// arguments from a vector
template<
typename... Args,
typename Fn>
Function pack_function(Fn && fn) {
return pack<0, Args...>(
[fn = std::forward<decltype(fn)>(fn)]
(Arguments arguments, Args const &... args)
{
return fn(args...);
});
}
Using this, you can pack any function up to be the same type:
Function fn =
pack_function<int, int>([] (auto lhs, auto rhs) {return lhs - rhs;});
You can then have them in a map, and call them using some vector, parsed from some input:
int main(int, char**) {
std::map<std::string, Function> operations;
operations ["add"] = pack_function<int, int>(add);
operations ["sub"] = pack_function<int, int>(
[](auto lhs, auto rhs) { return lhs - rhs;});
operations ["sum"] = [] (auto summands) {
int result = 0;
for (auto e : summands) {
result += e;
}
return result;
};
std::string line;
while (std::getline(std::cin, line)) {
std::istringstream command{line};
std::string operation;
command >> operation;
std::vector<int> arguments {
std::istream_iterator<int>{command},
std::istream_iterator<int>{} };
auto function = operations.find(operation);
if (function != operations.end ()) {
std::cout << line << " = ";
try {
std::cout << function->second(arguments);
} catch (std::string const & error) {
std::cout << error;
}
std::cout << std::endl;
}
}
return 0;
}
A live demo of the above code is here.
How to handle the overloaded function? It's true that I can distinguish the overloaded functions by the method of typeid, but it's far from a real implementation.
As you see, you don't need to, if you pack the relevant information into the function. Btw, typeid shouldn't be used for anything but diagnostics, as it's not guaranteed to return different strings with different types.
Now, finally, to handle functions that don't only take a different number of arguments, but also differ in the types of their arguments, you need to unify those types into a single one. That's normally called a "sum type", and very easy to achieve in languages like Haskell:
data Sum = IVal Int | SVal String
-- A value of type Sum is either an Int or a String
In C++ this is a lot harder to achieve, but a simple sketch could look such:
struct Base {
virtual ~Base() = 0;
};
inline Base::~Base() {}
template<typename Target>
struct Storage : public Base {
Target value;
};
struct Any {
std::unique_ptr<Base const> value;
template<typename Target>
Target const & as(void) const {
return
dynamic_cast<Storage<Target> const &>(*value).value;
}
};
template<typename Target>
auto make_any(Target && value) {
return Any{std::make_unique<Storage<Target>>(value)};
}
But this is only a rough sketch, since there's boost::any which should work perfectly for this case. Note that the above and also boost::any are not quite like a real sum type (they can be any type, not just one from a given selection), but that shouldn't matter in your case.
I hope this gets you started :)
Since you had problems adding multi type support I expanded a bit on the above sketch and got it working. The code is far from being production ready, though: I'm throwing strings around and don't talk to me about perfect forwarding :D
The main change to the above Any class is the use of a shared pointer instead of a unique one. This is only because it saved me from writing copy and move constructors and assignment operators.
Apart from that I added a member function to be able to print an Any value to a stream and added the respective operator:
struct Base {
virtual ~Base() = 0;
virtual void print_to(std::ostream &) const = 0;
};
inline Base::~Base() {}
template<typename Target>
struct Storage : public Base {
Target value;
Storage (Target t) // screw perfect forwarding :D
: value(std::forward<Target>(t)) {}
void print_to(std::ostream & stream) const {
stream << value;
}
};
struct Any {
std::shared_ptr<Base const> value;
template<typename Target>
Target const & as(void) const {
return
dynamic_cast<Storage<Target> const &>(*value).value;
}
template<typename T>
operator T const &(void) const {
return as<T>();
}
friend std::ostream & operator<<(std::ostream& stream, Any const & thing) {
thing.value->print_to(stream);
return stream;
}
};
template<typename Target>
Any make_any(Target && value) {
return Any{std::make_shared<Storage<typename std::remove_reference<Target>::type> const>(std::forward<Target>(value))};
}
I also wrote a small "parsing" function which shows how to turn a raw literal into an Any value containing (in this case) either an integer, a double or a string value:
Any parse_literal(std::string const & literal) {
try {
std::size_t next;
auto integer = std::stoi(literal, & next);
if (next == literal.size()) {
return make_any (integer);
}
auto floating = std::stod(literal, & next);
if (next == literal. size()) {
return make_any (floating);
}
} catch (std::invalid_argument const &) {}
// not very sensible, string literals should better be
// enclosed in some form of quotes, but that's the
// job of the parser
return make_any<std:: string> (std::string{literal});
}
std::istream & operator>>(std::istream & stream, Any & thing) {
std::string raw;
if (stream >> raw) {
thing = parse_literal (raw);
}
return stream;
}
By also providing operator>> it's possible to keep using istream_iterators for input.
The packing functions (or more precisely the functions returned by them) are also modified: When passing an element from the arguments vector to the next function, an conversion from Any to the respective argument type is performed. This may also fail, in which case a std::bad_cast is caught and an informative message rethrown. The innermost function (the lambda created inside pack_function) wraps its result into an make_any call.
add 5 4 = 9
sub 3 2 = 1
add 1 2 3 = wrong number of arguments, expected 2 but got 3
add 4 = wrong number of arguments, expected 2 but got 1
sum 1 2 3 4 = 10
sum = 0
sub 3 1.5 = argument 1 has wrong type
addf 3 3.4 = argument 0 has wrong type
addf 3.0 3.4 = 6.4
hi Pete = Hello Pete, how are you?
An example similar to the previous one can be found here. I need to add that this Any type doesn't support implicit type conversions, so when you have an Any with an int stored, you cannot pass that to an function expecting a double. Though this can be implemented (by manually providing a lot of conversion rules).
But I also saw your update, so I took that code and applied the necessary modifications to run with my presented solution:
Any apply (multimap<string, Function> const & map, string const & name, Arguments arguments) {
auto range = map.equal_range(name);
for (auto function = range.first;
function != range.second;
++function) {
try {
return (function->second)(arguments);
} catch (string const &) {}
}
throw string {" no such function "};
}
int eg(int a,int b){ return a+b;}
int eg(int a,int b, string c){return a+b+c.length();}
double eh(string a){return a.size()/double(2);}
int main(){
multimap<string, Function> func_map;
func_map.insert(make_pair(
"eg",pack_function<int,int>(
static_cast<int(*)(int, int)>(&eg))));
func_map.insert(make_pair(
"eg",pack_function<int,int,string>(
static_cast<int (*)(int, int, string)>(&eg))));
func_map.insert(make_pair(
"eh",pack_function<string>(eh)));
// auto p1=make_tuple(1,2);
// if you want tuples, just write a
// function to covert them to a vector
// of Any.
Arguments p1 =
{make_any (1), make_any (2)};
int result1 =
apply(func_map, "eg", p1).as<int>();
vector<Any> p2{p1};
p2.push_back(make_any<string> ("test"));
int result2 =
apply(func_map, "eg", p2).as<int>();
Arguments p3 = {make_any<string>("testagain")};
double result3 =
apply(func_map, "eh", p3).as<double>();
cout << result1 << endl;
cout << result2 << endl;
cout << result3 << endl;
return 0;
}
It doesn't use tuples, but you could write a (template recursive) function to access each element of a tuple, wrap it into an Any and pack it inside a vector.
Also I'm not sure why the implicit conversion from Any doesn't work when initialising the result variables.
Hm, converting it to use boost::any shouldn't be that difficult. First, the make_any would just use boost::any's constructor:
template<typename T>
boost::any make_any(T&& value) {
return boost::any{std::forward<T>(value)};
}
In the pack function, the only thing that I'd guess needs to be changed is the "extraction" of the correct type from the current element in the arguments vector. Currently this is as simple as arguments.at(N), relying on implicit conversion to the required type. Since boost::any doesn't support implicit conversion, you need to use boost::any_cast to get to the underlying value:
template<
std::size_t N,
typename Arg,
typename... Args,
typename Fn>
Function pack(Fn && fn) {
return pack<N+1, Args...>(
[fn = std::forward<decltype(fn)>(fn)]
(Arguments arguments, Args const &... args)
{
try {
return fn(
arguments,
boost::any_cast<Arg>(arguments.at(N)),
args...);
} catch (boost::bad_any_cast const &) { // throws different type of exception
throw std::string{"argument "} + std::to_string (N) +
std::string{" has wrong type "};
}
});
}
And of course, if you use it like in the example you provided you also need to use boost::any_cast to access the result value.
This should (in theory) do it, eventually you need to add some std::remove_reference "magic" to the template parameter of the boost::any_cast calls, but I doubt that this is neccessary.
(typename std::remove_reference<T>::type instead of just T)
Though I currently cannot test any of the above.