|
Boost : |
Subject: [boost] [local_function] passing local functions as template parameters
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2010-09-12 11:41:29
Hello all,
Can you please check if the following mechanism can be used to pass
local functor classes as template parameters?
PROBLEM
If I understand the C++ standard right, local classes cannot be passed
as template parameters. Because of that, if I am defining a functor to
pass to `std::for_each` I have to define it outside the local scope,
far from the `for_each` call, which is not ideal (from cplusplus.com):
struct myclass {
void operator() (int i) {cout << " " << i;}
} myobject;
int main () {
// Ideally `myclass` would be defined here locally...
vector<int> myvector;
myvector.push_back(10);
myvector.push_back(20);
myvector.push_back(30);
cout << "\nmyvector contains:";
for_each (myvector.begin(), myvector.end(), myobject);
cout << endl;
return 0;
}
The code above does not compile on GCC if `myclass` is defined locally
within `main`'s scope (it still compiles on MSVC instead...).
SOLUTION (?)
The following mechanism allows to define the functor body locally (in
a local function which also binds the in-scope parameter `x`) and then
pass it as a template parameter (to `boost::bind()` and then to
`std::for_each()`). The trick is for the local function to override
the virtual body of a global class and then pass the local function as
a pointer to the global class while dynamic binding will actually
execute the locally overridden body code.
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <algorithm>
#include <vector>
template<typename F> struct lfn_global {};
template<typename A1> struct lfn_global<void (A1)> { virtual void body(A1) {} };
// Similarly define `lfn_global` for other function arities and return types.
int main () {
double x = 5.6;
struct lfn_t: lfn_global<void (int)> {
lfn_t(double const& bound_x): x(bound_x) {}
void body(int i) {
std::cout << " " << i + x; // Local func body.
}
private:
double const& x;
} lfn_obj(x); // x is const& bound from scope.
boost::function<void (int)> lfn = boost::bind(
&lfn_global<void (int)>::body,
(lfn_global<void (int)>*)(&lfn_obj),
_1);
std::vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
std::cout << "v: ";
std::for_each(v.begin(), v.end(), lfn); // I can pass the local functor!
std::cout << std::endl;
return 0;
}
This code compiles on both GCC and MSVC, it correctly prints "v: 15.6
25.6 35.6". If this indeed works, I can hide all the extra code it
requires behind the `BOOST_LOCAL_FUNCTION...` macros.
Can you please try this code on other compilers? Do you see any issue
with this code?
Thank you very much.
-- Lorenzo
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk