你有三个问题:
boost::phoenix::function<>
是惰性的,因此必须对其进行两次评估才能获得实际结果。
rouletteWheelSelector::operator()
必须是 const 才能被boost::phoenix::function<>
.
sel
正在按值捕获stations
,因此将迭代器返回到已破坏的集合中;用于通过 const-referenceboost::phoenix::cref
捕获。stations
这段代码使用 VC++ 2010 SP1 和 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);
}
如果您使用的是 Phoenix v2 而不是 Phoenix v3,正如@jpalecek 在他现在已删除的答案中正确指出的那样,您必须在而不是使用嵌套result<>
模板:rouletteWheelSelector
result_type
struct rouletteWheelSelector
{
template<typename>
struct result
{
typedef BTSSet::iterator type;
};
BTSSet::iterator operator ()(BTSSet const& stations) const
{
return stations.begin();
}
};
然而,说了这么多,你为什么要boost::phoenix::function<>
在这里使用?为了您的使用,Greedy<>
没有它可以更容易(和有效地)实现:
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);
}
}