从迭代器中选择的函数类型成员变量
Function-typed member variable selecting from iterators
目标
- 一个class,带有函数类型的成员变量,可用于从两个迭代器表示的值范围中选择一个值
- 应该在 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
的 the/a 正确类型是什么?
尝试与思考
我试过用std::function
来输入choose_from
,但是由于没有抽象迭代器类型(AFAIK),我基本上停留在std::function<E(IT?, IT?)>
.
如果 Producer::next()
中 std::vector
的使用被泄露,我可以修复 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 额外的间接寻址)。它应该只在 运行 时间多态性不可避免时使用(例如动态回调)——这里不是这种情况。请勿使用。
目标
- 一个class,带有函数类型的成员变量,可用于从两个迭代器表示的值范围中选择一个值
- 应该在 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
的 the/a 正确类型是什么?
尝试与思考
我试过用
std::function
来输入choose_from
,但是由于没有抽象迭代器类型(AFAIK),我基本上停留在std::function<E(IT?, IT?)>
.如果
Producer::next()
中std::vector
的使用被泄露,我可以修复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 额外的间接寻址)。它应该只在 运行 时间多态性不可避免时使用(例如动态回调)——这里不是这种情况。请勿使用。