这是我在这里发表的第一篇文章,如果我不尊重“方式和风俗”,那就很好了:)
我是使用Boost :: Phoenix的新手,我希望将函数传递给定义如下的方法:
template <typename Selector>
Result Greedy (
const t_Capacity& capacity,
BTSSet stations,
BTSSet startSet)
{
//...
function <Selector> sel;
while ( !stations.empty() ) {
BTSSet::iterator currentStation = sel(stations);
// ...
}
// ...
}
我的选择器功能是:
struct rouletteWheelSelector {
typedef BTSSet::iterator result_type;
BTSSet::iterator operator () ( const BTSSet& stations ) {
// ...
}
};
但是我的编译器说没有办法从from 'typename detail::expression::function_eval<rouletteWheelSelector, set<BTS *, BTS_Cmp, allocator<BTS *> > >::type const'
转换为BTSSet :: Iterator。
我的算子声明好吗?如何强制编译器推导出正确的sel返回类型?
谢谢!
答案 0 :(得分:1)
你有三个问题:
boost::phoenix::function<>
是懒惰的,因此必须对其进行两次评估才能获得实际结果。rouletteWheelSelector::operator()
必须为const才能由boost::phoenix::function<>
使用。sel
按值捕获stations
,从而将迭代器返回到已销毁的集合中;使用boost::phoenix::cref
通过const-reference捕获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
模板,而不是{{1 }}:
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<>