这是递推_计数_C++中各种类型任意嵌套Iterable实现的if函数和递推_计数_具有指定值的if函数_C++中各种类型任意嵌套Iterable实现的类型的后续问题.在深入研究了检测函数的参数类型的内容之后,我发现可以用Boost.CallableTraits图书馆中的boost::callable_traits::args_t语法简化最后实现中的D5参数。因此,recursive_count_if模板函数完全可以作为以下代码使用。
std::vector> v = {{"hello"}, {"world"}};
auto size5 = [](std::string s) { return s.size() == 5; };
auto n = recursive_count_if(v, size5);recursive_count_if函数的自动类型推导实现:
#include
// recursive_count_if implementation
template requires (is_iterable && std::same_as>, boost::callable_traits::args_t>)
auto recursive_count_if(const T1& input, const T2 predicate)
{
return std::count_if(input.begin(), input.end(), predicate);
}
// transform_reduce version
template requires (is_iterable && !std::same_as>, boost::callable_traits::args_t>)
auto recursive_count_if(const T1& input, const T2 predicate)
{
return std::transform_reduce(std::begin(input), std::end(input), std::size_t{}, std::plus(), [predicate](auto& element) {
return recursive_count_if(element, predicate);
});
}使用的is_iterable概念:
template
concept is_iterable = requires(T x)
{
*std::begin(x);
std::end(x);
};使用的The约束
因为输入lambda函数中的类型扮演终止条件的角色,所以这里不能使用auto关键字作为泛型lambda。如果传入类似于[](auto element) { }的lambda函数,编译错误将弹出。如果要使用泛型lambdas,可能可以选择上一版本recursive_count_if函数,因为终止条件是分开的。
欢迎所有建议。
摘要资料:
recursive_count_if模板函数是boost依赖的,从输入的lambda参数可以自动推导出终止条件的类型。recursive_count_if模板函数的requires子句有点复杂,并且依赖于boost。如果有更简单的方法做这件事,请告诉我。发布于 2020-11-19 16:37:43
由于库克斯普鲁松在前面问题的注释中,不应该尝试确定谓词函数参数的类型,这肯定会失败。实际上,当您查看谓词时,问题立即开始:
auto size5 = [](std::string s) { return s.size() == 5; };想一想:嘿,那是在复制s,我应该把它传递给const reference:
auto size5 = [](const std::string &s) { return s.size() == 5; };现在,函数的requires子句失败了。在将类型与std::same_as进行比较之前,您可能可以添加更多的技巧来丢弃cv-限定符和引用,但这也不能涵盖所有可能的情况。例如,我可以编写一个lambda,它允许检查任何类型的std::basic_string:
auto size5 = [](std::basic_string s) { return s.size() == 5; };正如我在注释中所建议的那样,您只想编写一个概念,检查谓词是否可以应用于其输入的参数,而不需要检查类型本身。以下是一个可能的实现:
template
concept is_applicable_to_elements = requires(Pred predicate, const T &container)
{
predicate(*container.begin());
};
template requires is_applicable_to_elements
auto recursive_count_if(const T1& input, const T2 predicate)
{
return std::count_if(input.begin(), input.end(), predicate);
}
template
auto recursive_count_if(const T1& input, const T2 predicate)
{
return std::transform_reduce(std::begin(input), std::end(input), std::size_t{}, std::plus(), [predicate](auto& element) {
return recursive_count_if(element, predicate);
});
}注意,由于所有模板都使用了is_iterable(),所以可以删除该要求,但是如果保留它,如果您不小心尝试将recursive_count_if()应用于不支持迭代的东西,则会得到更好的错误消息。
https://codereview.stackexchange.com/questions/252325
复制相似问题