Я решил использовать подход, когда функция шаблона пытается вывести максимальное количество аргументов, которые можно было бы вызвать с помощью проведенного < /code>, который не может быть конвертируемым для 'inment'.
Код: Выделить всё
namespace detail {
namespace {
struct probe
{
template
consteval operator T const &() const noexcept;
template
consteval operator T const &&() const noexcept;
template
consteval operator T&() const noexcept;
template
consteval operator T&&() const noexcept;
};
template
requires(N < 15)
consteval size_t probeMaxArgs()
{
constexpr auto probeN =
[](std::index_sequence) -> bool
{
return std::is_invocable_v ||
std::is_invocable_v;
};
constexpr std::array results =
[&](std::index_sequence)
{
return std::array{probeN(std::make_index_sequence())...};
}(std::make_index_sequence());
constexpr size_t result =
[&]
{
size_t r = size_t(-1);
for (size_t i = 0; i < results.size(); ++i)
r = results[i] ? i : r;
return r;
}();
static_assert(result != size_t(-1), "Failed to deduce max args");
return result;
}
} // namespace
} // namespace detail
< /code>
работает с шаблонами Lambdas и с параметрами по умолчанию. < /p>
static_assert(0 == detail::probeMaxArgs());
static_assert(1 == detail::probeMaxArgs());
static_assert(3 == detail::probeMaxArgs());
static_assert(3 == detail::probeMaxArgs());
< /code>
, но не с шаблонными понятиями < /p>
constexpr auto sort =
[]<
// std::ranges::random_access_range R, //< doesn't compile
typename R, //< compiles
typename Comp = std::ranges::less,
typename Proj = std::identity>(R&& r, Comp comp = {}, Proj proj = {})
// -> std::ranges::borrowed_range auto { //< doesn't compile
{
// std::ranges::sort(r, comp, proj); //< wtf doesn't compile
return std::forward(r);
};
static_assert(3 == detail::probeMaxArgs());
< /code>
Если я не пошутил какую -либо строку с концепцией, компиляция не сбои. Подход, это может быть многообещающим: < /p>
template
struct get {
template
static constexpr auto op = &F::template operator();
};
using get_l = get;
// compiles
template
constexpr auto op_l = get_l::op;
// doesn't: only one parameter
// template
// constexpr auto op_l = get_l::op;
< /code>
Тем не менее, он не будет работать с параметрами без типа. Полагаю, можно попробовать с Auto
Подробнее здесь: https://stackoverflow.com/questions/797 ... h-concepts