0

我有一个sequence类似于的结构std::integer_sequence,但它可以保存多种类型的值作为非类型模板参数(有点像编译时元组)。它可以std::integer_sequence通过使用constexpr构造函数和用户定义的推导指南隐式构造。我还有一个apply_constexpr将非类型模板参数包应用于函数的函数,类似于std::apply. 他们来了:

template <auto...>
struct sequence {
    template <typename T, T... Ts>
    constexpr sequence(std::integer_sequence<T, Ts...>) noexcept {
    }
};

template <typename T, T... Ts>
sequence(std::integer_sequence<T, Ts...>) -> sequence<Ts...>;

template<typename Fn, auto... Vals>
constexpr std::invoke_result_t<Fn, decltype(Vals)...>
apply_constexpr(Fn&& fn, sequence<Vals...>)
noexcept(std::is_nothrow_invocable_v<Fn, decltype(Vals)...>) {
    return fn(std::forward<decltype(Vals)>(Vals)...);
}

它们可以这样使用:

static_assert(apply_constexpr(
    [&](auto&&... i) { return ((f(i) == g(i)) && ...); },
    sequence{ std::make_index_sequence<100>() })
);

sequence像上面那样明确构造时,一切都很好。但是,因为构造函数不是explicit以下也有效:

sequence s = std::make_index_sequence<100>();

但是尽管它有效,但以下内容不起作用(candidate template ignored: could not match 'sequence' against 'integer_sequence'):

static_assert(apply_constexpr(
    [&](auto&&... i) { return ((f(i) == g(i)) && ...); },
    std::make_index_sequence<100>())
// no "sequence{ ... }" here, trying to rely on implicit conversion
);

为什么它不起作用,我该怎么做才能使它起作用?

4

1 回答 1

1

您可以将重载转发到您的第一个apply_constexpr函数。像这样的东西。

template<typename Fn, typename Is>
constexpr auto apply_constexpr(Fn&& fn, Is s)
noexcept(noexcept(apply_constexpr(fn, sequence{s}))) {
    return apply_constexpr(std::forward<Fn>(fn), sequence{s});
}

它首先不起作用的原因是模板推导总是在确切的类型上。推导时编译器不会考虑转换。如果你通过 a std::integer_sequence,这就是编译器将推断出的。

语言不支持一步换算。

于 2021-01-02T20:02:09.743 回答