Lambda functions as class members - c++

Is it possible to accept two different types of lambda function as class members without knowing their template arguments ahead of time?
struct two_functors {
std::function<???> a;
std::function<???> b;
...
};
Such that something like this would be possible:
void main(){
vector<two_functors> many_functors;
int a = 2;
int b = 3;
double c = 4.7;
double d = 8.4;
two_functors add_and_subtract;
add_and_subtract.a = [a, b](int x, int y){cout << x + y << endl;};
add_and_subtract.b = [c, d](double x, double y){cout << x - y << endl;};
two_functors multiply_and_divide;
multiply_and_divide.a = [c, d](double x, double y){cout << x * y << endl;};
multiply_and_divide.b = [a, b](int x, int y){cout << x / y << endl;};
many_functors.push_back(add_and_subtract);
many_functors.push_back(multiply_and_divide);
for (auto functors : many_functors){
functors.a();
functors.b();
}
}

If you just want to construct two_functors at various times, but execute them later in sequence all at once, you could just use the captured data.
struct two_functors
{
function<void ()> a;
function<void ()> b;
};
int main()
{
vector<two_functors> many_functors;
int a = 2;
int b = 3;
double c = 4.7;
double d = 8.4;
two_functors add_and_subtract {
[a, b](){cout << a + b << endl;},
[c, d](){cout << c - d << endl;}
};
two_functors multiply_and_divide {
[c, d](){cout << c * d << endl;},
[a, b](){cout << a / b << endl;}
};
many_functors.push_back(add_and_subtract);
many_functors.push_back(multiply_and_divide);
for (auto functors : many_functors){
functors.a();
functors.b();
}
}

That's essentially a tuple. You can see how the interface is implemented for that.
template< class F0, class F1 >
struct two_functors {
F0 func0;
F1 func1;
};
template< class F0, class F1 >
two_functors<F0, F1> make_two_functor( F0&& f0, F1&& f1 )
{
// Added [std::forward][2]
return two_functors<F0,F1>( std::forward<F0>(f0), std::forward<F1>(f1) );
}

Not an attempt to answer (I just need the formatting feat), just a variation of Steven's proposal
template<typename A, typename B>
two_functors<A,B> make_two_functors(A&& a, B&& b) {
return two_functors<A,B> {a, b};
}
Does that have any downside compared to using std::forward<T>?
Btw - I somehow wish the need for such "makers" would have vanished with C++11.

An alternative to Steven's answer would be to use an intermediate "umbrella" class.
EDIT: Just compiled an example on g++ (GCC) 4.5.3
#include <functional>
#include <iostream>
using namespace std;
class myfunction
{
};
template <typename T>
class specificFunction : public myfunction
{
public:
function<T> f;
specificFunction(function<T> pf)
{
f = pf;
}
};
struct two_functors {
myfunction* a;
myfunction* b;
};
int main()
{
myfunction* f = new specificFunction<void(int,int)> ([](int a, int b) { cout << a << " - " << b << endl; });
myfunction* f2 = new specificFunction<void(double,int)> ([](double a, int b) { cout << a << " - " << b << endl; });
two_functors tf;
tf.a = f;
tf.b = f2;
((specificFunction<void(int,int)>*)(tf.a))->f(4,5);
((specificFunction<void(double,int)>*)(tf.b))->f(4.02,5);
}

Related

Pass a variable number of arguments into a function

I know how to use variadic templates and ellipses to accept a variable number of arguments, but how do you pass a variable number of arguments into a function?
Take the following code for example:
#include <iostream>
struct A {
A(int a, int b) : x(a), y(b) {}
int x, y;
};
struct B {
B(int a, int b, int c) : x(a), y(b), z(c) {}
int x, y, z;
};
template<typename T, typename... TArgs>
T* createElement(TArgs&&... MArgs) {
T* element = new T(std::forward<TArgs>(MArgs)...);
return element;
}
int main() {
int Aargs[] = { 1, 2 };
int Bargs[] = { 1, 2, 3 };
A* a = createElement<A>(Aargs); //ERROR
B* b = createElement<B>(Bargs); //ERROR
std::cout << "a.x: " << a->x << "\na.y: " << a->y << "\n" << std::endl;
std::cout << "b.x: " << b->x << "\nb.y: " << b->y << "\nb.z: " << b->z << "\n" << std::endl;
delete a;
delete b;
}
Is there any way to expand the arrays so that each of their values is like an argument being passed to the function (similar to parameter pack expansion)?
Or, if not, is there any other way to make this work?
You can expand the array using a std::index_sequence
#include <iostream>
#include <utility>
struct A {
A(int a, int b) : x(a), y(b) {}
int x, y;
};
struct B {
B(int a, int b, int c) : x(a), y(b), z(c) {}
int x, y, z;
};
template<typename T, typename... TArgs>
T* createElement(TArgs&&... MArgs) {
T* element = new T(std::forward<TArgs>(MArgs)...);
return element;
}
template<typename T, typename U, size_t... I>
T* createElementFromArrayHelper(std::index_sequence<I...>, U* a){
return createElement<T>(a[I]...);
}
template<typename T, typename U, size_t N>
T* createElementFromArray(U (&a)[N]){
return createElementFromArrayHelper<T>(std::make_index_sequence<N>{}, a);
}
int main() {
int Aargs[] = { 1, 2 };
int Bargs[] = { 1, 2, 3 };
A* a = createElementFromArray<A>(Aargs);
B* b = createElementFromArray<B>(Bargs);
std::cout << "a.x: " << a->x << "\na.y: " << a->y << "\n" << std::endl;
std::cout << "b.x: " << b->x << "\nb.y: " << b->y << "\nb.z: " << b->z << "\n" << std::endl;
delete a;
delete b;
}

My template class's ctor takes a callable object as an argument but cannot be initialized from it?

I've been asked to implement a desktop calculator using std::function through a Function table for binary operators only. So I have this code:
#include <functional>
#include <iostream>
#include <string>
int main()
{
std::map<std::string, std::function<int(int, int)>> binOp;
binOp["+"] = [](int a, int b){return a + b;};
binOp["*"] = [](int a, int b){return a * b;};
binOp["-"] = [](int a, int b){return a - b;};
binOp["/"] = [](int a, int b){return a / b;};
binOp["%"] = [](int a, int b){return a % b;};
for(const auto& p : binOp)
std::cout << 9 << " " << p.first << " " << 8 << " = " << p.second(9, 8) << std::endl;
}
* The program works fine for binary operators for integer operands. What I thought to make my class template to be generic which handles different types of operands int, double, std::string... So I've tried this on my own with the help of decltype:
template <typename T>
struct BinOp
{
BinOp() = default;
BinOp(T f) : fn(f){}
std::function<T> fn;
using arg_type = decltype(fn(0, 0));
arg_type operator()(arg_type a, arg_type b){return fn(a, b);}
};
int main()
{
std::map<std::string, BinOp<int(int, int)>> calc;
calc["+"] = BinOp<int(int, int)>([](int x, int y){return x + y;});
calc["*"] = BinOp<int(int, int)>([](int x, int y){return x * y;});
calc["-"] = BinOp<int(int, int)>([](int x, int y){return x - y;});
calc["/"] = BinOp<int(int, int)>([](int x, int y){return x / y;});
calc["%"] = BinOp<int(int, int)>([](int x, int y){return x % y;});
for(const auto& e : calc)
std::cout << 10 << " " << e.first << " " << 12 <<
" = " << e.second(10, 12) << endl;
//BinOp<std::string(std::string, std::string)> bstr = [](string s1, string s2){return s1 + s2;}; // it doesn't work?
BinOp<std::string(std::string, std::string)> bstr;
bstr.fn = [](string s1, string s2){return s1 + s2;}; // works fine!
std::cout << bstr("Hello ", "Wold!") << std::endl;
std::cout << "\nDone!\n";
}
So why I am not able to initialize bstr from a Lambda expression although class BinOp has a constructor that takes a callable? But assigning to bstr is fine: bstr = [](){}... // works!
Any tip or suggestion, critic is highly appreciated. Thank you.
You can use direct initialisation here to construct a BinOp directly:
BinOp<std::string(std::string, std::string)> bstr {[](string s1, string s2){return s1 + s2;}};
The reason why your original code won't compile is likely because you are asking the compiler to perform two conversions, and that it won't do.

Set up member function that grants const access to members

I have a class with some huge objects that I need to access in a const fashion. To do that I have the getABC() member function that copies these objects to the outside world. Is it possible to directly access them, since the copy operations are very slow in my case? shared_ptr would be preferable, and also I want to avoid making tuples just to return them in the getABC()
#include <iostream>
#include <vector>
using namespace std;
class foo {
private:
int a;
vector<int> b; // HUGE OBJECT
vector<int> c; // HUGE OBJECT
public:
foo(int a_, vector<int> b_, vector<int> c_) : a(a_), b(b_), c(c_) { }
void printfoo() {
cout << "a = " << a << endl;
cout << "b = ";
for(auto v:b) {
cout << v << " ";
}
cout << endl;
cout << "c = ";
for(auto v:c) {
cout << v << " ";
}
cout << endl;
}
void getABC(int & a_in, vector<int> & b_in, vector<int> & c_in ) const {
a_in = a;
b_in = b; // SLOW
c_in = c; // SLOW
}
};
int main() {
int in = 4;
vector<int> inA {1, 2, 3, 5};
vector<int> inB {2, 2, 3, 5};
foo bar(in, inA, inB);
bar.printfoo();
// GET THE MEMBERS
int out = 0;
vector<int> outA;
vector<int> outB;
bar.getABC(out, outA, outB);
// PRINT
cout << "OUT = " << out;
cout << "\nOUTA = ";
for(auto const &v : outA ) {
cout << v << " ";
}
cout << endl;
cout << "OUTB = ";
for(auto const &v : outA ) {
cout << v << " ";
}
cout << endl;
return 0;
}
I want to avoid making tuples just to return them in the getABC()
Why? It seems the most straightforward way to return references to multiple pieces of data:
tuple<const int&, const vector<int>&, const vector<int>&> getABC() const
{ return std::make_tuple(std::cref(a), std::cref(b), std::cref(c)); }
auto refs = bar.getABC();
for (auto& x : std::get<1>(refs))
// ...
Or create a named struct to return instead:
struct DataRefs {
int a;
const std::vector<int>& b;
const std::vector<int>& c;
};
DataRefs getABC() const { return { a, b, c }; }
This has the advantage that you don't need to use std::get<N> to access the members, and can just use sensible names:
auto refs = bar.getABC();
for (auto& x : refs.b)
// ...
From your comment maybe you want something like this, but this would be a dumb interface:
void getABC(const int*& pa, const std::vector<int>*& pb, const std::vector<int>*& pc) const
{
pa = &a;
pb = &b;
pc = &c;
}
Which you could use like this:
int* a;
std::vector<int>* b;
std::vector<int>* c;
bar.getABC(a, b, c);
for (auto& x : *b)
// ...
As you can see, this is more verbose for the caller, and is just ugly and not idiomatic C++.
Or you could move the data into a separate sub-object:
class foo
{
struct data
{
int a;
std::vector<int> b;
std::vector<int> c;
};
data m_data;
public:
const data& getData() const { return m_data; };
};
auto& refs = bar.getData();
for (auto& x : refs.b)
// ...
You could have 3 separate functions that return const references (not necessary for the int):
class foo {
...
int getA() const { return a; }
const vector<int>& getB() const { return b; }
const vector<int>& getC() const { return c; }
};
These can even be inlined by the compiler so you don't need to actually put them anywhere. Just call bar.getB() whenever you need to use b. Even without inlining you're most likely not going to notice a performance hit.

runtime specialization of overloaded function

This is a variant of this SO question. I have an overloaded function that takes parameters of different types and returns different types:
struct mystruct {
auto f (int x, int y) -> int;
auto f (std::string x, int y) -> float;
};
The function f needs to call itself with one of its parameters specialized a number of times.
I'd like to define a function that specializes the parameter y, that is I'd want g(z) = f(z,y). The return type of g and the type of its unique parameter z variable, but the implementation is the same in both cases.
The best implementation I could find of this situation is overloading the lambda function:
template <class F1, class F2>
struct overload_set : F1, F2
{
overload_set(F1 f1, F2 f2) : F1(f1), F2(f2) {}
using F1::operator();
using F2::operator();
};
template <class F1, class F2>
overload_set<F1, F2> overload(F1 f1, F2 f2) {
return overload_set<F1, F2>(f1, f2);
};
struct mystruct {
auto f( std::string x, int y) -> float {
return y+9.3;
}
auto f( int x, int y) -> int
{
auto g = overload (
[=]( int z ) -> int {return f(z,y);},
[=]( std::string z) -> float { return f(z,y); }
);
if ( x == 0 ) {
std::cout << g("this string") << "\n";
return 0;
}
if ( x == 1 ) return y;
return 7;
}
};
int main () {
mystruct h;
std::cout << h.f(1,4) << "\n";
std::cout << h.f(0,2) << "\n";
}
which works as expected but seems overkill. It seems that a simple preprocessor macro of the form
#define k(z) f(z,y)
would also work. Is there a good way of achieving this?
Not sure if this is what you are attempting to do but here is a working (c++14) example:
#include <iostream>
struct mystruct {
static auto f (int x, int y) -> int {
std::cout << "f(" << x << "," << y << ")" << std::endl;
auto g = [=](auto z) -> decltype(mystruct::f(z, y)) {
return mystruct::f(z, y);
};
if (x < 1)
g("end");
else
g(x - 1);
}
static auto f (std::string x, int y) -> float {
std::cout << "f(\"" << x << "\"," << y << ")" << std::endl;
}
};
int main() {
mystruct::f(10, 1);
}
Output:
f(10,1)
f(9,1)
f(8,1)
f(7,1)
f(6,1)
f(5,1)
f(4,1)
f(3,1)
f(2,1)
f(1,1)
f(0,1)
f("end",1)
Am I missing something?
This produces the same answer, and I think is a little clearer:
#include <string>
#include <iostream>
struct mystruct
{
auto f( std::string x, int y) -> float {
return y+9.3;
}
auto f( int x, int y) -> int
{
switch(x)
{
case 0: {
auto g = [=](auto...args) { return f(args..., y); };
std::cout << g("this string") << "\n";
return 0;
} break;
case 1: {
return y;
} break;
default:
return 7;
}
}
};
int main () {
mystruct h;
std::cout << h.f(1,4) << "\n";
std::cout << h.f(0,2) << "\n";
}
Maybe in reality there are more switch cases, and g needs to be hoisted above the switch statement?

C++ std::function variable with varying arguments

In my callback system I want to store std::function (or something else) with varying arguments.
Example:
I want to call void()
I want to call void(int, int)
I want 1) and 2) to be stored in the same variable and choose what to call in actuall call
FunctionPointer f0;
FunctionPointer f2;
f0();
f2(4, 5);
Is it possible to do something like this? Or I have to create several "FuntionPointer" templates based on input arguments count.
EDIT
Is it possible to utilize std::bind somehow for this task? With std::bind I can have std::function<void()> f = std::bind(test, 2, 5);
EDIT 2
Practical use case: I have a trigger system and I want to assign funtion pointers to actions, so when action happen, function is called.
Pseudo-code sample:
structure Trigger
{
Function f;
}
Init:
Trigger0.f = pointer to some function ()
Trigger1.f = pointer to some function (a, b)
Input:
Find Trigger by input
if (in == A) Trigger.f();
else Trigger.f(10, 20)
or if possible
Input:
Find Trigger by input
if (in == A) f = bind(Trigger.f);
else f = bind(Trigger.f, 10, 20);
f()
std::function<void()> and std::function<void(int, int)> are two absolutely distinct types. You need some sort of union functionality (or polymorphism) to store an object of an unknown type.
If you can use Boost, you could easily do this with boost::variant:
// Declaration:
boost::variant<std::function<void()>, std::function<void(int, int)> > f;
// Calling, explicit:
if (fContainsNullary()) {
boost::get<std::function<void()>>(f)();
} else {
boost::get<std::function<void(int, int)>>(f)(4, 5);
}
It is up to you to provide the logic of fContainsNullary(). Alternatively, you can use the variant's own stored knowledge of value type by using a visitor:
struct MyVisitor : boost::static_visitor<void>
{
result_type operator() (const std::function<void()> &a) {
a();
}
result_type operator() (const std::function<void(int, int)> &a) {
a(4, 5);
}
};
// Calling, via visitor:
boost::apply_visitor(MyVisitor(), f);
If Boost is not an option, you can hand-craft a suitable union for much the same purpose.
The following solution might work for you (I'm not sure that the code is absolutely correct here):
Create a wrapper for std::function with virtual destructor to enable using dynamic cast
class function_wrapper_base
{
virtual ~function_wrapper_base();
}
template <class... Args>
class function_wrapper
: public function_wrapper_base
{
public:
std::function<void, Args...> f;
...
};
Then create a class variant_function_holder
class variant_function_holder
{
std::unique_ptr<function_wrapper_base> f;
...
template <class... Args>
void operator()(Args&&... args)
{
function_wrapper<std::decay<Args>::type...> * g = dynamic_cast<function_wrapper<std::decay<Args>::type...>>(f.get());
if (g == nullptr)
{
// ToDo
}
g->f(std::forward<Args>(args)...);
}
};
Well, if you can use RTTI, you can define a MultiFuncObject like this, and you can easily bind other functions. Also, you can easily call them. But unfortunately, this approach only works for a limited number of arguments. But actually boost::bind also supports limited number of arguments (by default 9). So you can extend this class to satisfy your needs.
Before giving you the source of MultiFuncObject, I want to show you how you can use it. It takes an template argument to be used as return type. You can bind new functions with += operator. With some template magic, the class distinguishes differences between bound functions with same count of arguments with at least one different argument type.
You need C++11, because MultiFuncObject uses std::unordered_map and std::type_index.
Here is usage:
#include <iostream>
using namespace std;
void _1() {
cout << "_1" << endl;
}
void _2(char x) {
cout << "_2" << " " << x << endl;
}
void _3(int x) {
cout << "_3" << " " << x << endl;
}
void _4(double x) {
cout << "_4" << " " << x << endl;
}
void _5(int a, int b) {
cout << "_5" << " " << a << " " << b << endl;
}
void _6(char a, int b) {
cout << "_6" << " " << a << " " << b << endl;
}
void _7(int a, int b, int c) {
cout << "_7" << " " << a << " " << b << " " << c << endl;
}
int main() {
MultiFuncObject<void> funcs;
funcs += &_1;
funcs += &_2;
funcs += &_3;
funcs += &_4;
funcs += &_5;
funcs += &_6;
funcs += &_7;
funcs();
funcs('a');
funcs(56);
funcs(5.5);
funcs(2, 5);
funcs('q', 6);
funcs(1, 2, 3);
return 0;
}
I hope this is close to what you want. Here is the source of MultiFuncObject:
#include <typeinfo>
#include <typeindex>
#include <unordered_map>
using namespace std;
template <typename R>
class MultiFuncObject {
unordered_map<type_index, void (*)()> m_funcs;
public:
MultiFuncObject<R> operator +=( R (* f)() ) {
m_funcs[typeid( R() )] = (void (*)()) f;
return *this;
}
template <typename A1>
MultiFuncObject<R> operator +=( R (* f)(A1) ) {
m_funcs[typeid( R(A1) )] = (void (*)()) f;
return *this;
}
template <typename A1, typename A2>
MultiFuncObject<R> operator +=( R (* f)(A1, A2) ) {
m_funcs[typeid( R(A1, A2) )] = (void (*)()) f;
return *this;
}
template <typename A1, typename A2, typename A3>
MultiFuncObject<R> operator +=( R (* f)(A1, A2, A3) ) {
m_funcs[typeid( R(A1, A2, A3) )] = (void (*)()) f;
return *this;
}
R operator()() const
{
unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R() ));
if (it != m_funcs.end()) {
R (*f)() = ( R (*)() )(it->second);
(*f)();
}
}
template <typename A1>
R operator()(A1 a1) const
{
unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R(A1) ));
if (it != m_funcs.end()) {
R (*f)(A1) = ( R (*)(A1) )(it->second);
(*f)(a1);
}
}
template <typename A1, typename A2>
R operator()(A1 a1, A2 a2) const
{
unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R(A1, A2) ));
if (it != m_funcs.end()) {
R (*f)(A1, A2) = ( R (*)(A1, A2) )(it->second);
(*f)(a1, a2);
}
}
template <typename A1, typename A2, typename A3>
R operator()(A1 a1, A2 a2, A3 a3) const
{
unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R(A1, A2, A3) ));
if (it != m_funcs.end()) {
R (*f)(A1, A2, A3) = ( R (*)(A1, A2, A3) )(it->second);
(*f)(a1, a2, a3);
}
}
};
It stores different function prototypes using std::unordered_map with keys of std::type_index and values of void (*)(). When needed, the correct function is retrieved using that map.
Here is the working example
C++11 to the rescue!
If you can generalize your function to a functor object taking no arguments, then you can call it with any lambda.
#include <iostream>
using namespace std;
template <class F>
void call_it(F&& f)
{
f();
}
int main()
{
int x = 50, y = 75;
call_it([] () { cout << "Hello!\n"; });
call_it([x,y] () { cout << x << " + " << y << " = " << x + y << '\n';});
return 0;
}
If std::function is not necessary for you, you can create a proxy class.
class fn_t {
public:
typedef void (*fn_1_t)();
typedef void (*fn_2_t)(int, int);
fn_1_t fn_1;
fn_2_t fn_2;
fn_t operator=(fn_1_t func_1) { fn_1 = func_1; return *this; }
fn_t operator=(fn_2_t func_2) { fn_2 = func_2; return *this; }
void operator()() { (*fn_1)(); }
void operator()(int a, int b) { (*fn_2)(a, b); }
};
#include <iostream>
using namespace std;
void first() {
cout << "first" << endl;
}
void second(int a, int b) {
cout << "second " << a << " : " << b << endl;
}
int main() {
fn_t f;
f = &first;
f = &second;
f();
f(5, 4);
return 0;
}
Class fn_t automatically works with two prototypes you want, assigns automatically needed one, and it can call functions with both prototypes by overlading () operator with appropriate parameters.
You may want to check for validity of function pointers fn_1 and fn_2 but I didn't include this checking for minimality.
The advantage of this is that you only need C++ and not even STL and Boost.
The other answers are fine but I want to show my solution as well.
It's a small header with which you can "elongate" function signatures.
This allows you to do this (extract from the github example):
int foo_1p(int a);
int foo_2p(int a, int b);
int foo_3p(int a, int b, int c);
int foo_4p(int a, int b, int c, int d);
int foo_5p(int a, int b, int c, int d, int e);
int foo_6p(int a, int b, int c, int d, int e, int f);
int foo_7p(int a, int b, int c, int d, int e, int f, std::string g);
...
int main()
{
std::unordered_map<std::string, std::function<int(int, int, int, int, int, int, std::string)>> map;
map["foo_1p"] = ex::bind(foo_1p, ph, ph, ph, ph, ph, ph);
map["foo_2p"] = ex::bind(foo_2p, ph, ph, ph, ph, ph);
map["foo_3p"] = ex::bind(foo_3p, ph, ph, ph, ph);
map["foo_4p"] = ex::bind(foo_4p, ph, ph, ph);
map["foo_5p"] = ex::bind(foo_5p, ph, ph);
map["foo_6p"] = ex::bind(foo_6p, ph);
map["foo_7p"] = foo_7p;
for (const auto& f : map)
{
std::cout << f.first << " = " << f.second(1, 1, 1, 1, 1, 1, "101") << std::endl;
}
}