【问题标题】:Writing C++11 LINQ-style Select编写 C++11 LINQ 风格的选择
【发布时间】:2012-11-06 21:21:16
【问题描述】:

我正在尝试为我的基类 Iterator 编写 LINQ 样式的方法,List 和 Sequence 将从中继承,但是这两个容器将有自己的这些方法的实现。 “Where”方法非常简单。 “选择”方法非常棘手;你不能有虚拟模板方法。

  template <typename T>
  class Iterator {
  public:
    virtual ~Iterator() {};

    // This is illegal, but if it weren't, it would be the functionality I want.
    template <typename R>
    virtual shared_ptr<IIterator<R>> Select(const function<R(T)>& func) = 0;

    virtual shared_ptr<IIterator<T>> Where(const function<bool(T)>& func) = 0;
  };

“选择”将允许您将“火腿三明治”类型的迭代器转换为“生菜”类型的迭代器。

HamSandwiches->选择([] (shared_ptr hs) { return hs->Lettuce; });

忽略单引号。

既然我们不能有虚拟模板函数,我当然不能把函数变成虚拟函数。在这种情况下,我们有一个普通的旧函数,与虚函数相比,我们永远不应该通过在 List 和 Sequence 中编写实现来“隐藏”它的实现;这将被视为设计缺陷。

  template <typename T>
  class Iterator {
  public:
    virtual ~Iterator() {};

    template <typename R>
    shared_ptr<Iterator<R>> Select(const function<R(T)>& func);

    virtual shared_ptr<Iterator<T>> Where(const function<bool(T)>& func) = 0;
  };

  template <typename T>
  template <typename R>
  shared_ptr<Iterator<R>> Iterator<T>::Select(const function<R(T)>& func) {
    //Implementation - What would it be?
  }

现在我们必须在我们的基类中实现,这个实现需要特定于 List 和 Sequence。根据我所见,您将开始创建受保护的“实现函数”来执行“选择”中可能被列表或序列覆盖的某些操作。

我不是在这里寻找一个确切的答案,我正在寻找可以帮助我到达我可能/应该想去的地方的东西。有没有人发现任何常见的陷阱或我可能做错的事情?

【问题讨论】:

标签: c++ linq select c++11 where


【解决方案1】:

选项 1

我看到的在 C++ 中实现 LINQ 的想法根本不依赖于虚拟方法。相反,每个结果都包装在一个模板类中返回,大致如下:

template <class T>
class RangeWrapper
{
public:
    template <class U>
    Select(U u) -> decltype(...) {
        return RangeWrapper<SelectRange, U>(_myRange, u);
    }

private:
    T& _myRange;
};

如果你链接其中的几个,返回类型可能会变得很大,但这是在编译时完成所有事情的代价。

选项 2

您可以实现类型擦除以始终返回 Iterator&lt;T&gt; 类型的迭代器。这应该很容易使用网络上的类型擦除迭代器库来实现(有很多,你可以看看 boost.TypeErasure 已被接受但尚未发布)。 或者,您可以在 boost 中使用 any_range,如果您可以使用范围(它们比迭代器更自然地映射到 LINQ)。

选项 3

如果您不将此作为培训练习,那么已经实施了多种解决方案。使用谷歌。值得注意的是,Microsoft itself is working on a C++ Linq to implement the reactive extensions on top of it

【讨论】:

  • 我认为这对我来说是一个很好的答案。我会说我永远不会使用 boost,因为库对我来说太大了。对于迭代,我有另一种处理它们的方法。 Microsoft Linq 可能是我最终可能会使用的并且只是围绕这些扩展(如果可以的话),因为如果 Microsoft 有一个实现,它肯定会比我的更好。 ;)
  • @TIHan : Boost 不是库,它是库的集合。挑选你需要的——没有人使用所有的Boost(一次)。
  • @ildjarn,选择 Boost 中的哪些库最有意义。我可能最终会在某一时刻这样做。我只是有点害怕尝试选择,因为我必须找出哪些库依赖于什么。
  • @TIHan :幸运的是,Boost 附带了一个实用程序,可以为您执行依赖检查。 :-] BCP
猜你喜欢
  • 2010-11-08
  • 2014-10-20
  • 2012-01-12
  • 1970-01-01
  • 1970-01-01
  • 2011-12-12
  • 1970-01-01
  • 2012-09-16
  • 1970-01-01
相关资源
最近更新 更多