尽管用户提供了推导指南,但仍忽略了候选模板
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
,编译器将推导出此内容。
该语言不支持一次转换和推导。
我有一个类似于 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
,编译器将推导出此内容。
该语言不支持一次转换和推导。