Перегрузка шаблона посетителя С++

Я провел последние часы, пытаясь найти элегантное решение, но не смог.

Описание: я хотел бы иметь реализацию по умолчанию для функтора посетителя в классе visitor_base_all, а затем каждый из производных классов, например, visitor_override, определял бы метод именно для того, что ему нужно. Я понимаю, что это не работает, потому что оператор() не передается производным классам (из-за того, что С++ не перегружает области видимости, что достаточно справедливо), поэтому вопрос в том, как это сделать? Я думал сделать это с перегруженными лямбда-выражениями или иметь переключатель в виртуальном методе базового класса, а затем каждый производный класс перегружает только виртуальные методы, вызываемые в этом переключателе.

Что касается лямбд, я не уверен, как это сделать. Я уже читал следующее: pablo_arias arne-mertz и stack_overflow_question, но я все еще немного смущен тем, что было бы правильным правильным путем вперед.

Спасибо за ваше время

Короткий вопрос: Правильный способ С++ 17 для компиляции/работы ниже. Каков правильный способ обобщить его для большого количества производных типов в вариантах и ​​производных классах?

(Добавить комментарии-редактировать) Моя проблема более обобщена для большого количества классов и гораздо большего количества типов, поэтому, если возможно, я бы предпочел как-то шаблонировать/обобщать ее. Ниже приведен пример только с 1 производным классом, но как правильно иметь 10 классов? (Я бы не хотел объявлять использование в каждом из них, если этого можно избежать).

#include <variant>

struct A{};
struct B{};
struct C{};
using type_x = std::variant<A,B,C>;

class base_class
{
protected:
    struct visitor_base_all
    {
        void operator()(const A& a){std::cout<<"A_base" << std::endl;}
        void operator()(const B& b){std::cout<<"B_base" << std::endl;}
        void operator()(const C& c){std::cout<<"C_base" << std::endl;}
    };
    virtual void run(type_x evt){return std::visit(visitor_base_all{}, evt);}
};

class derived_class :public base_class
{
    struct visitor_override : public visitor_base_all
    {
        void operator()(const C& c){};
    };
     virtual void run(type_x evt){return std::visit(visitor_override{}, evt);}
};

person eucristian    schedule 29.10.2019    source источник
comment
Можете ли вы предоставить минимально воспроизводимый пример, на котором могут быть основаны решения?   -  person bracco23    schedule 29.10.2019
comment
Я думаю, вы хотите изучить использование декларации. using visitor_base_all::operator(); внутри visitor_override должно помочь.   -  person n. 1.8e9-where's-my-share m.    schedule 29.10.2019
comment
@Barry: Даже если using является решением в обоих случаях, проблема OP заключается не в нескольких базовых классах, а в сокрытии методов-членов ... Не в более подходящих дубликатах IMO.   -  person Jarod42    schedule 29.10.2019
comment
Хм. @ Барри, мне не сразу понятно, как это дубликат (этот вопрос о посетителях, другой о множественном наследовании ... на первый взгляд не так много совпадений) или как связанные ответы отвечают на этот вопрос.   -  person Konrad Rudolph    schedule 29.10.2019
comment
@Jarod42, вы можете отредактировать повторяющееся разрешение, добавить еще один повторяющийся вопрос и/или удалить неподходящий.   -  person n. 1.8e9-where's-my-share m.    schedule 29.10.2019
comment
@KonradRudolph Это точная копия. Причина, по которой код OP не работает, заключается в том, что мы не объединяем две разные области, и вам нужно объявление using, чтобы ввести другие имена. Тот факт, что это дело конкретно о посетителях, значения не имеет.   -  person Barry    schedule 29.10.2019
comment
@KonradRudolph обман вопрос не слишком похож, но его ответ отлично подходит и для этого вопроса. Вы можете добавить другие дубликаты, если найдете более подходящий (их много).   -  person n. 1.8e9-where's-my-share m.    schedule 29.10.2019
comment
В этом случае, как только мы находим имя в производной, мы не продолжаем поиск в базе... вместо того, чтобы найти имя в разных базах, мы его не рассматриваем. Но это тот же фундаментальный принцип (который даже цитируется в ОП) с тем же решением.   -  person Barry    schedule 29.10.2019
comment
Возможно, лучшим решением было бы сделать void operator() виртуальным и просто переопределить то, что вам нужно. Вот как обычно работает шаблон посетителя. Если вы обнаружите, что вам не нужно, чтобы он был виртуальным, вы, вероятно, неправильно используете шаблон.   -  person n. 1.8e9-where's-my-share m.    schedule 29.10.2019
comment
Прошу прощения, мой вопрос недостаточно ясен. Я знаю, как решить проблему компиляции, но моя проблема в том, что у меня много производных классов и много случаев, и я бы не хотел использовать base::operator() в каждом из них, так как это было бы очень уродливо (даже если бы у меня был макрос для него, все равно уродливо имхо) Опять же, мой плохой и ваши комментарии действительны. ничего, если я немного отредактирую вопрос? На основании правок я бы сказал, что это больше не дубликат?   -  person eucristian    schedule 29.10.2019
comment
@eucrisian: у вас есть цепочки производных классов? один, который реализует operator() для A, другой для B и последний для C, или он просто задан по умолчанию или предоставлен?   -  person Jarod42    schedule 29.10.2019
comment
@ Jarod42 да, точно. но я видел в одном из дубликатов Барри шаблон коллектора. теперь точно знаю, как это реализовать. пробую сейчас   -  person eucristian    schedule 29.10.2019
comment
Вы ищете что-то вроде что   -  person Jarod42    schedule 29.10.2019
comment
да. это все. Большое спасибо, мистер Джарод @ Jarod42   -  person eucristian    schedule 29.10.2019
comment
@ Jarod42, можно ли сделать ваш пример с вариативными шаблонами?   -  person eucristian    schedule 29.10.2019
comment
@eucrisian: я бы сказал да с рекурсией.   -  person Jarod42    schedule 29.10.2019
comment
Давайте продолжим обсуждение в чате.   -  person eucristian    schedule 29.10.2019