How to pass a function in parameter with Boost::Phoenix?
It's my first post here so plese be kind if I 开发者_开发问答don't respect the "ways and customs" :)
I'm new using Boost::Phoenix and I want to pass a function to a methods defined like :
template <typename Selector>
Result Greedy (
const t_Capacity& capacity,
BTSSet stations,
BTSSet startSet)
{
//...
function <Selector> sel;
while ( !stations.empty() ) {
BTSSet::iterator currentStation = sel(stations);
// ...
}
// ...
}
My selector function is :
struct rouletteWheelSelector {
typedef BTSSet::iterator result_type;
BTSSet::iterator operator () ( const BTSSet& stations ) {
// ...
}
};
But my compiler says there's no way to convert from from 'typename detail::expression::function_eval<rouletteWheelSelector, set<BTS *, BTS_Cmp, allocator<BTS *> > >::type const'
to BTSSet::Iterator.
Is my functor declaration ok ? How can I force the compiler to deduce the right return type of sel ?
Thank you !
You have three issues:
boost::phoenix::function<>
is lazy, so it must be evaluated twice in order to get an actual result.rouletteWheelSelector::operator()
must be const in order to be used byboost::phoenix::function<>
.sel
is capturingstations
by value, and consequently returning an iterator into a destroyed set; useboost::phoenix::cref
to capturestations
by const-reference.
This code compiles and runs cleanly for me with VC++ 2010 SP1 and Boost 1.47.0:
#include <memory>
#include <set>
#include <boost/phoenix.hpp>
struct BTS
{
explicit BTS(int const val_) : val(val_) { }
int val;
};
struct BTS_Cmp
{
typedef bool result_type;
bool operator ()(BTS const* const a, BTS const* const b) const
{
if (a && b)
return a->val < b->val;
if (!a && !b)
return false;
return !a;
}
};
typedef std::set<BTS*, BTS_Cmp> BTSSet;
struct rouletteWheelSelector
{
typedef BTSSet::iterator result_type;
BTSSet::iterator operator ()(BTSSet const& stations) const
{
return stations.begin();
}
};
template<typename Selector>
void Greedy(BTSSet stations)
{
namespace phx = boost::phoenix;
phx::function<Selector> sel;
while (!stations.empty())
{
BTSSet::iterator currentStation = sel(phx::cref(stations))();
std::auto_ptr<BTS> deleter(*currentStation);
stations.erase(currentStation);
}
}
int main()
{
BTSSet stations;
stations.insert(new BTS(1));
stations.insert(new BTS(2));
stations.insert(new BTS(3));
stations.insert(new BTS(4));
stations.insert(new BTS(5));
Greedy<rouletteWheelSelector>(stations);
}
If you're using Phoenix v2 rather than Phoenix v3, as @jpalecek correctly noted in his now-deleted answer, you must use a nested result<>
template inside of rouletteWheelSelector
rather than result_type
:
struct rouletteWheelSelector
{
template<typename>
struct result
{
typedef BTSSet::iterator type;
};
BTSSet::iterator operator ()(BTSSet const& stations) const
{
return stations.begin();
}
};
However, all that said, why are you using boost::phoenix::function<>
at all here? For your usage, Greedy<>
could more easily (and efficiently) be implemented without it:
template<typename Selector>
void Greedy(BTSSet stations)
{
Selector sel;
while (!stations.empty())
{
BTSSet::iterator currentStation = sel(stations);
std::auto_ptr<BTS> deleter(*currentStation);
stations.erase(currentStation);
}
}
精彩评论