3

我正在编写一些代码,并且我有一个部分可以执行一次性排序功能。为了实现它,我决定重载 operator< 函数是最简单的。我更愿意做的是通过使用某种 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 函数时,我迷失了方向。

谢谢您的帮助。

4

1 回答 1

1

我相信你可以通过大量的帮助来扭转局面

  • 提升凤凰bindlambda
  • 增强绑定protect

但是,我学会了避免这些情况。编辑事实上,请参阅下面的一个这样的装置。我发现这非常容易出错并且难以推理。

从本质上讲,您所看到的违反了得墨忒耳法则。如果您“只是”编写代码(而不是在 lambda 中),那么它已经处理了太多任务。

所以我要做的第一件事就是重新考虑班级设计。

我要做的第二件事是 /extract/ 从您的比较器中承担不同的责任。请注意,比较器做了三件事:

  • 访问 lhs 中 X 的 c_str()
  • 访问 rhs 中 X 的 c_str()
  • 比较两者

前两个步骤是提取的明确候选者。让我们编写首先保留的通用比较器:

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)))
    );
于 2014-02-21T15:29:51.853 回答