我正在处理一些代码,我有一个部分,我做一次性排序功能。为了实现它,我认为最简单的方法是重载运算符<功能。我更喜欢做的是通过使用某种boost :: bind,boost :: phoenix,lambda或其他类型的实现来将类型的实现更接近实际调用。不幸的是,我无法访问新的C ++ 11功能。下面是一些示例代码。
// In a header
struct foo
{
char * a;
char * c_str() { return a; }
}
// In a header
struct bar
{
foo * X;
bar(foo * _X) : X(_X) {}
bool operator < (const bar& rhs) const
{
return std::string(X->c_str()) < std::string(rhs.X->c_str());
}
};
struct bars : public std::vector<bar> { ... some stuff };
// Some other header
bars Bs;
// A cpp file
... other stuff happens that fills the Xs vector with objects
...::Function()
{
// Current use and it works fine
std::sort(Bs.begin(), Bs.end())
// Would like something that accomplishes this:
// std::sort(Bs.begin(), Bs.end(),
// std::string(lhs.X->c_str()) < std::string(rhs.X->c_str()))
// A non-working example of what I'm trying to do
// std::sort(Xs.begin(), Xs.end(),
// std::string((bind(bar::X->c_str(), _1)) <
// std::string((bind(bar::X->c_str(), _2)) )
}
在试图弄清楚如何访问成员指针,成员函数然后将结果全部转换为boost :: bind函数时,我迷路了。
感谢您的帮助。
答案 0 :(得分:1)
我确信你可以使用
的充分帮助来改变你的方式bind
和lambda
protect
但是,我学会了避免这些情况。 编辑事实上,请参阅下面的一个这样的装置。我发现这非常容易出错并且难以推理。
你所看到的实质上是违反了Law Of Demeter。如果你“只是”编写代码(不是在lambda中),那么它已经处理了太多的任务。
所以我要做的第一件事就是重新思考班级设计。
我要做的第二件事是从比较器中提取/提取不同的责任。请注意,比较器执行三项操作:
前两个步骤是明确的提取候选者。让我们编写首先保留的通用比较器:
template <typename F>
struct compare_by_impl {
compare_by_impl(F f = F{}) : _f(std::move(f)) {}
template <typename T, typename U>
bool operator()(T const& a, U const& b) const {
return _f(a) < _f(b);
}
private:
F _f;
};
与往常一样,拥有可以推导出访问者类型的工厂函数是很好的(如果您只是在那里使用Phoenix,它将节省您指定表达式模板中涉及的(奥术)类型名称):
template <typename Accessor>
compare_by_impl<Accessor> comparer_by(Accessor&& f) {
return compare_by_impl<Accessor>(std::forward<Accessor>(f));
}
现在您已经可以通过排序调用移动实现了:
void Function()
{
struct accessX_c_str {
std::string operator()(bar const& b) const {
return b.X->c_str();
}
};
std::sort(Bs.begin(), Bs.end(), comparer_by(accessX_c_str()));
}
我个人将它留在那里。
这是一些更加扭曲的装置:
// to avoid `comparer_by`
std::sort(Bs.begin(), Bs.end(), phx::bind(accessX_c_str(), arg1) < phx::bind(accessX_c_str(), arg2));
// to avoid any helper types (!?!?!? untested!)
std::sort(Bs.begin(), Bs.end(),
phx::construct<std::string>(phx::bind(&foo::c_str, phx::lambda [ phx::bind(&bar::X, arg1) ](arg1)))
< phx::construct<std::string>(phx::bind(&foo::c_str, phx::lambda [ phx::bind(&bar::X, arg1) ](arg2)))
);