微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从迭代器中选择的函数类型成员变量 目标问题和解决方案草图问题尝试和想法

如何解决从迭代器中选择的函数类型成员变量 目标问题和解决方案草图问题尝试和想法

目标

  • 具有函数类型成员变量的类,可用于从由两个迭代器表示的一系列值中选择一个
  • 应该可以在 C++14 中工作,但如果只有 17 或 20 年才有(更好)的解决方案,我仍然会感兴趣

问题和解决方案草图

以下是设想的解决方案的草图,其中 ??? 表示选择函数的类型,我无法计算。

template<typename E>
class Producer {
  ??? choose_from; // A function It × It → E
  ...
public:
  Producer(??? cf): choose_from{cf} {}

  E next() {
    // Get a bunch of values from internal state (omitted for brevity).
    // Could also be another container,e.g. std::set.
    std::vector<E> values = ...;

    return choose_from(values.begin(),values.end());
  }
}

接下来,是一些此类 Producer 的示例用法草图。仅支持其中一部分的解决方案仍然可以。

  • 结合现有功能

    auto p = Producer<int>(std::max_element)`;
    
  • 与 lambda 函数结合使用:

    auto p = Producer<int>([](auto begin,auto end)) { ... });
    
  • 结合自定义免费功能

    template<typename E,typename It>
    E my_selector(It begin,It end) { ... }
    
    auto p = Producer<int>(my_selector);
    

问题

如何让代码工作,即成员变量 choose_from 的正确类型是什么?

尝试和想法

  • 我尝试使用 std::function 来输入 choose_from,但由于没有抽象迭代器类型 (AFAIK),我基本上被困在 std::function<E(IT?,IT?)>

  • 如果 std::vectorProducer::next() 的使用被泄露,我可以修复 choose_from 的类型来处理 std::vector<E>::iterator,但我更愿意隐藏内部细节。

解决方法

std::min_element 是一个函数模板,它本身并不能做太多事情。函数模板有问题 - 它们不能作为模板参数传递,nor 作为函数参数。

如果您可以将其包装在通用 lambda 中,那么可能有一个通用解决方案:

template<class E,class F>
class Producer {
    F choose_from; // A function It - It → It

public:
    Producer(F const& cf) : choose_from{ cf } {}

    E next() {
        std::vector<E> values{ 5,2,3 };

        return *choose_from(values.begin(),values.end());
    }
};

template<typename E,typename F>
auto make_producer(F const& cf) {
    return Producer<E,F>(cf);
}

template<typename It>
It my_selector(It begin,It end) { return begin; }

int main() {
    auto p1 = make_producer<int>([](auto from,auto to) { return from; });
    cout << p1.next() << endl;
    auto p2 = make_producer<int>([](auto from,auto to) { return std::min_element(from,to); });
    cout << p2.next() << endl;
    auto p3 = make_producer<int>([](auto from,auto to) { return my_selector(from,to); });
    cout << p3.next() << endl;
}

注意事项:

  • 也没有部分 CTAD,因此即使在 C++17 中,您也需要一个辅助函数(上面的make_producer())。

  • std::function 带有运行时开销(1..2 个额外的间接访问)。只有在运行时多态不可避免时才应该使用它(例如动态回调)——这里不是这种情况。不要使用。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。