Кандидат шаблона игнорируется, несмотря на предоставленное пользователем руководство по выводу

У меня есть структура, похожая на , но она может содержать значения нескольких типов в качестве нетиповых параметров шаблона (вроде кортежа времени компиляции). Он неявно конструируется из 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, это то, что сделает компилятор.

Выполнение преобразований и выводов за один шаг не поддерживается языком.

Другие вопросы по тегам