尽管用户提供了推导指南,但仍忽略了候选模板

Template candidate ignored despite a user provided deduction guide

我有一个类似于 std::integer_sequence 的结构 sequence,但它可以将多种类型的值保存为非类型模板参数(有点像编译时元组)。它可以通过使用 constexpr 构造函数和用户定义的推导指南从 std::integer_sequence 隐式构造。我还有一个函数 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
);

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

您可以重载转发到您的第一个 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});
}

首先它不起作用的原因是模板推导总是在确切的类型上。推导时编译器不会考虑转换。如果您传递 std::integer_sequence,编译器将推导出此内容。

该语言不支持一次转换和推导。