Кандидат шаблона игнорируется, несмотря на предоставленное пользователем руководство по выводу
У меня есть структура, похожая на , но она может содержать значения нескольких типов в качестве нетиповых параметров шаблона (вроде кортежа времени компиляции). Он неявно конструируется из
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
);
Почему это не работает и что я могу сделать, чтобы заставить его работать?
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});
}
Причина, по которой это не работает, в первую очередь заключается в том, что вывод шаблона всегда выполняется на точном типе. При выводе компилятор не будет учитывать преобразования. Если вы пройдете
std::integer_sequence
, это то, что сделает компилятор.
Выполнение преобразований и выводов за один шаг не поддерживается языком.