如何在 constexpr 上下文中调用 ExecutionPolicy 算法?

问题描述 投票:0回答:0

我想用

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
?当然,我的另一种方法也会对我有所帮助。

c++ c++20 constexpr stl-algorithm
© www.soinside.com 2019 - 2024. All rights reserved.