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;
}
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.
I have defined a boost::variant var like this:
boost::variant<boost::blank, bool, int> foo;
This variable, when instantiated but not initialized, has a value of type boost::blank, because boost::blank is the first type passed to the templated boost::variant.
At some point, I want to know if foo has been initialized. I've tried this, but with no good results:
if (foo) //doesn't compile
if (foo != boost::blank()) //doesn't compile
if (!(foo == boost::blank())) //doesn't compile
I think it's worth noticing that, when foo has been initialized (eg., foo = true), it can be "reset" by doing foo = boost::blank();.
How can I check if foo has been initialized, ie, it has a different type than boost::blank?
You could define a visitor to detect the 'blankness':
struct is_blank_f : boost::static_visitor<bool> {
bool operator()(boost::blank) const { return true; }
template<typename T>
bool operator()(T const&) const { return false; }
};
Use it like so:
bool is_blank(my_variant const& v) {
return boost::apply_visitor(is_blank_f(), v);
}
When the first type is "active", foo.which() == 0. Use that.
Returns: The zero-based index into the set of bounded types of the contained type of *this. (For instance, if called on a variant<int, std::string> object containing a std::string, which() would return 1.)
(http://www.boost.org/doc/libs/1_58_0/doc/html/boost/variant.html#idp288369344-bb)
I would like to do the following. Say I have this:
void f(const char* c) {
// Do stuff with c
}
void g(const char* c, int x, int y) {
// Do other stuff
}
What I'd like to do is to create a function from g that takes a const char* c. That is:
int a = 5;
int b = 9;
expression(g, a, b)("Hi!");
Preferably, expression(g) can be stored in a variable as well. I'm not sure how to declare this variable either.
I have tried using boost::bind; however boost::bind returns a boost::function, and I would like a normal C++ function pointer. Additionally, I also saw this thread:
demote boost::function to a plain function pointer
And neither of the top two solution will work. My function f is constrained to take one parameter (no void* user_data pointer). The reason I need this is that I have a third function, h, that takes in a function of one argument, namely a const char* and does things with it. I'd like to be able to pass in a form of g to h.
h(f) // Valid
h(expression(g, a, b)) // Would like for this to be valid, too
I'm not sure if this is possible, but if it is, do tell :).
Use bind:
#include <functional>
auto h = std::bind(g, std::placeholders::_1, 5, 9);
h("hi");
bind makes copies of the arguments, so beware if you're planning on taking arguments by reference (in which case you may want std::ref). Try to keep the result type auto to avoid unnecessary conversions.
To get a normal C++ function:
void h(char const * s) { g(s, 5, 9); }
Or:
void (*ph)(char const *) = [](const char * s) { g(s, 5, 9); };
Or for the insane:
struct Foo { static void bar(char const * s) { g(s, 5, 9); } };
void (*qh)(char const *) = &Foo::bar;
Usage:
h("hi");
ph("hi");
Foo::bar("hi");
qh("hi");
Can someone explain the code below? I get confused when I try to understand how isNumeric!T works in this case.
auto foo(T)(T n) if (isNumeric!T) {
return (T m) {return m > n;};
}
void main() {
auto hoo5 = foo!int(1000);
writeln(hoo5(93));
writeln(hoo5(23));
}
Start with:
auto foo(T)(T n) if (isNumeric!T) {
// ignore this for now
}
foo is a generic function that takes one argument of its generic type. if (isNumeric!T) is a compile-time check from std.traits that guarantees foo's type is numeric. Non-numeric types won't work. Its return type is inferred and in this case is a delegate.
This:
(T m) {return m > n;}; //returned from foo
is a delegate literal (or closure). It's basically a function pointer with state. In this case, it closes over the parameter n passed to foo. In your example:
auto hoo5 = foo!int(1000);
is effectively translated to the function:
bool hoo5 (int x) { return x > 1000; }
So when you call hoo5, it returns a boolean indicating if its argument is greater than 1000 - but only in your specific case.
If you call foo like this:
auto hoo5 = foo!double(1.2345);
You get a reference to a function that returns a boolean indicating if its argument (a double) is greater than 1.2345.