Is it possible to create locally-local closures pre-C ++ 11?

With C ++ 11 we get lambdas and the ability to create functions / functors / closures on the fly, where we really need them, and not somewhere where they really don't belong. In C ++ 98/03, a good way to create local functor / closure functions would be to:

struct{ void operator()(int& item){ ++item; } }foo_functor; some_templated_func(some_args, foo_functor); 

Unfortunately, you cannot use local types for templates (Visual Studio allows this with language extensions enabled). My move, although then it went like this:

 struct X{ static void functor(int& item){ ++item; } }; some_templated_func(some_args, &X::functor); 

The obvious problem is that you cannot save any state, since local structures / classes cannot have static members.
My next thought to solve this problem was to use combinations of std::bind1st and std::mem_fun and non-static methods and variables, but unfortunately std::mem_fun somehow throttled using std::mem_fn(&X::functor) , which again may be due to the fact that the local structure / t in the templates:

 // wanted, not working solution struct X{ int n_; X(int n) : n_(n) {} void functor(int& item) const { item += n_; } }; X x(5); some_templated_func(some_args,std::bind1st(std::mem_fun(&X::functor),&x)); 

Failure to use VC9 and VC10 (with /Za , disabled language extensions) with the following error

 error C2893: Failed to specialize function template 'std::const_mem_fun1_t<_Result,_Ty,_Arg> std::mem_fun(_Result (_Ty::* )(_Arg) const)' With the following template arguments: 'void' 'main::X' 'int &' 

Or under gcc 4.3.4 with this error

 error: no matching function for call to 'mem_fun(void (main()::X::*)(int&))' 

Oddly enough, the VC9 / VC10 is still suffocating in the above example, even with language extensions:

 error C2535: 'void std::binder1st<_Fn2>::operator ()(int &) const' : member function already defined or declared 

So, as far as possible, the functionality stated in the title? Or am I making a mistake in the last example of how I use std::bind1st or std::mem_fun ?

+4
source share
3 answers

bind1st only works for binary functions, and overall it is very limited. mem_fn only works with non-stationary member functions; for your application you would like ptr_fun .

Indeed, the best tool for working in C ++ 03 is Boost Bind, or I'll demonstrate here tr1::bind , which (in my opinion) is more portable.

 #include <tr1/functional> #include <iostream> #include <algorithm> using namespace std::tr1::placeholders; int nums[] = { 1, 2, 4, 5, 6, 8 }; int main() { struct is_multiple { static bool fn( int mod, int num ) { return num % mod == 0; } }; int *n = std::find_if( nums, nums + sizeof nums/sizeof*nums, std::tr1::bind( is_multiple::fn, 3, _1 ) ); std::cout << n - nums << '\n'; } 
+4
source

Yes, you can, but you will have to implement one or more virtual methods declared in the interface.

 template<typename Arg, typename Result> struct my_unary_function { virtual Result operator()(Arg) = 0; }; template<typename Arg, typename Result> struct my_unary_functor { my_unary_function<Arg, Result> m_closure; my_unary_functor(my_unary_function<Arg, Result> closure) : m_closure(closure) {} Result operator()(Arg a) { return m_closure(a); } }; template<typename T, TFunctor> void some_templated_function( std::vector<T> items, TFunctor actor ); 

Then you can define and use local closure:

 void f() { std::vector<int> collection; struct closure : my_unary_function<int, int> { int m_x, m_y; closure(int x, int y) : m_x(x), m_y(y) {} virtual int operator()(int i) const { cout << m_x + m_y*i << "\t"; return (m_x - m_y) * i; } }; some_templated_function( collection, my_unary_functor<int,int>(closure(1, 5)) ); } 

Credit @Omnifarious for this improvement ( my_unary_functor not required):

 void f() { std::vector<int> collection; struct closure : my_unary_function<int, int> { int m_x, m_y; closure(int x, int y) : m_x(x), m_y(y) {} virtual int operator()(int i) const { cout << m_x + m_y*i << "\t"; return (m_x - m_y) * i; } }; // need a const reference here, to bind to a temporary const my_unary_functor<int,int>& closure_1_5 = my_unary_functor<int,int>(closure(1, 5)) some_templated_function( collection, closure_1_5 ); } 
+2
source

If this were possible in C ++ 03, why did C ++ 0x introduce lambdas? There is a reason for lambda, and that is because binding and all other C ++ 03 solutions suck terribly.

-1
source

All Articles