Как можно пропустить некоторые комбинации перегрузки вариантов типов в std :: visit? - PullRequest
0 голосов
/ 29 августа 2018

std::visit поддерживает несколько вариантов ввода. Однако код должен обрабатывать все комбинации типов из этих вариантов.

Есть ли способ пропустить не "значимые" комбинации?

например:

template<class... Ts> 
struct overloaded : Ts... { using Ts::operator()...; };

template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

int main() {
    std::variant<int, float, char> v1 { 's' };
    std::variant<int, float, char> v2 { 10 };

    std::visit(overloaded{
        [](int a, int b) { },
        [](int a, float b) { },
        [](int a, char b) { },
        [](float a, int b) { },
        [](float a, float b) { },
        [](float a, char b) { },
        [](char a, int b) { },
        [](char a, float b) { },
        [](char a, char b) { }
    }, v1, v2);

    return 0;
}

есть ли шанс реализовать только несколько важных комбинаций и «оставить» остальные? (конечно, прямо сейчас компилятор сообщит о неприятной ошибке, если вы забудете реализовать одну комбинацию ...)

Может быть, общие лямбды?

std::visit(overloaded{
        [](int a, int b) { },
        [](int a, float b) { },
        [](int a, char b) { },
        [](float a, int b) { },
        [](auto a, auto b) { }, // <<
    }, v1, v2);

Это работает, но мне интересно, есть ли лучшее решение?

Обновление: Вот площадка с решениями, упомянутыми в ответах: http://coliru.stacked -crooked.com / а / 78d9f2f25789bad2

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Другой вариант - изменить overloaded на что-то вроде этого:

template<class... Ts>
struct overloaded_or_no_op : Ts...
{
    using Ts::operator()...;

    template<class... Us>
    void operator()(const Us&...) const {  }
};

template<class... Ts> overloaded_or_no_op(Ts...) -> overloaded_or_no_op<Ts...>;
0 голосов
/ 29 августа 2018

Да, общие лямбды - очень хорошее решение. Ваше предлагаемое решение буквально работает ad litteram.

Применяются обычные правила перегрузки.

[](auto a, auto b)

эквивалентно в этом смысле с

template <class T1, class T2> auto foo(T1 a, T2 b) const;

Все, что не совпадает точно с одной из не шаблонных перегрузок, будет вызывать универсальную лямбду.

Вы можете немного перемешать, предоставив что-то вроде [] (int a, auto b) и [] (auto a, auto b). Все еще применяются обычные правила перегрузки.

Или еще больше перепутать с []<class T>(T a, T b) (начиная с C ++ 20)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...