Re[2]: перегрузки с приоритетами
От: vopl Россия  
Дата: 01.07.23 14:39
Оценка: 68 (1)
Здравствуйте, Кодт, Вы писали:


К>Что мне в ней не нравится концептуально:

К>1) если есть несколько подходящих перегрузок с разными приоритетами, и у той, что подходит лучше (меньшее количество преобразований типа) приоритет ниже, — до неё дело не дойдёт
К>2) если есть несколько подходящих перегрузок с одним приоритетом, — ошибка неоднозначности трактуется как неудача подстановки
К>3) наличие/отсутствие ограничений (concept, requires) не пробрасывается из семейства перегрузок в полиморфную лямбду и может создавать неоднозначность (и см. пункт 2)

первые два момента получилось закрыть примерно так
#include <iostream>

template <std::size_t v> struct prio : prio<v-1> {};
template <> struct prio<0> {};

void f(prio<0>, short) {std::cout << "short" << std::endl;}
void f(prio<1>, int)   {std::cout << "int"   << std::endl;}
void f(prio<2>, long)  {std::cout << "long"  << std::endl;}

template<class... Args>
constexpr bool invocableWith = requires(Args... args) {{f(args...)};};

template <std::size_t pv=10, class... Args>
requires invocableWith<prio<pv>, Args...>
void dispatch(Args... args)
{
    f(prio<pv>{}, args...);
}

template <std::size_t pv=10, class... Args>
requires (pv>0 && !invocableWith<prio<pv>, Args...>)
void dispatch(Args... args)
{
    dispatch<pv-1>(args...);
}

template <std::size_t pv, class... Args>
requires (pv==0 && !invocableWith<prio<pv>, Args...>)
void dispatch(Args... args) = delete;

int main()
{
    // выбор по второму аргументу
    dispatch(short{});
    dispatch(long{});
    dispatch(int{});

    // по второму аргументу коллизия, выбор по приоритету
    dispatch(unsigned{});
    dispatch(float{});

    // нет вариантов
    struct Bad{};
    //dispatch(Bad{});

    return 0;
}


https://gcc.godbolt.org/z/bTqzoWPWG
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.