我想用
ExecutionPolicy
调用标准库算法进行矢量化。同时调用也应该在 constexpr
上下文中工作。不幸的是,标准库中算法的 ExecutionPolicy
重载目前不是 constexpr
。当然,在编译时,是否使用向量化并不重要。所以在这种情况下,我只想在没有ExecutionPolicy
的情况下调用重载。
这我已经实现为:
#include <execution>
#include <functional>
#include <type_traits>
template <typename Fn, typename ... T>
constexpr decltype(auto) unseq_invoke(Fn&& fn, T&& ... v) {
using namespace std;
if (is_constant_evaluated()) {
return invoke(forward<Fn>(fn), forward<T>(v) ...);
} else {
return invoke(forward<Fn>(fn), execution::unseq, forward<T>(v) ...);
}
}
基本上,这也能正常工作:
#include <iostream>
#include <string_view>
constexpr bool is_valid_c_str(std::string_view const view) {
constexpr auto find_wrapper =
[]<typename ... T>(T&& ... v) {
return std::find(std::forward<T>(v) ...);
};
return unseq_invoke(find_wrapper, view.begin(), view.end(), 0) == view.end();
}
int main() {
using namespace std::literals;
static constexpr auto a = "valid c_str"sv;
static constexpr auto b = "invalid\0c_str"sv;
std::cout << std::boolalpha
<< a << ": " << is_valid_c_str(a) << '\n'
<< b << ": " << is_valid_c_str(b) << '\n';
static_assert(is_valid_c_str(a));
static_assert(!is_valid_c_str(b));
}
valid c_str: true
invalidc_str: false
问题是我总是必须在 lambda 中包装像
std::find
这样的函数。如果我尝试直接将它作为参数传递,我会收到 <unresolved overloaded function type>
错误。
return unseq_invoke(std::find, view.begin(), view.end(), 0) == view.end();
main.cpp: In function ‘constexpr bool is_valid_c_str(std::string_view)’:
main.cpp:21:24: error: no matching function for call to ‘unseq_invoke(<unresolved overloaded function type>, std::basic_string_view<char>::const_iterator, std::basic_string_view<char>::const_iterator, int)’
21 | return unseq_invoke(std::find, view.begin(), view.end(), 0) == view.end();
| ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:6:26: note: candidate: ‘template<class Fn, class ... T> constexpr decltype(auto) unseq_invoke(Fn&&, T&& ...)’
6 | constexpr decltype(auto) unseq_invoke(Fn&& fn, T&& ... v) {
| ^~~~~~~~~~~~
main.cpp:6:26: note: template argument deduction/substitution failed:
main.cpp:21:24: note: couldn’t deduce template parameter ‘Fn’
21 | return unseq_invoke(std::find, view.begin(), view.end(), 0) == view.end();
| ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
当然,我可以用宏来缩短它,但它仍然是一个显式包装器,我也不喜欢使用宏。
有没有办法让
unseq_invoke(std::algorithm, ...)
在没有包装纸的情况下工作std::algorithm
?当然,我的另一种方法也会对我有所帮助。