Я уже писал такой код, поэтому могу сказать, что это возможно.(Это было для коммерческой работы с закрытым исходным кодом, поэтому я боюсь, что не смогу показать вам код).Вы можете найти действительно хороший пример того, как это сделать, в библиотеке Boost.Variant, в частности http://svn.boost.org/svn/boost/trunk/boost/variant/detail/visitation_impl.hpp.Код очень плотный и продвинутый для C ++, поэтому для его полного понимания может потребоваться день или два.
Краткое резюме: шаблон класса boost::variant
работает как объединение с int, хранящим, какой членСоюз действителен.Функция «посещения» позволяет вам предоставить объекту функции перегруженный operator()
, который может принимать любого из возможных членов объединения, и он генерирует оператор switch, который обращается к соответствующему члену и вызывает правильную перегрузку operator()
для него.,Если вы уже находите это сложным для подражания, или вы еще не знаете о Boost.MPL, я предлагаю вам прекратить читать здесь, прочитать документацию Boost.Variant, а затем переписать свой класс, чтобы иметь возможность использовать это: умныйребята из Boost уже сделали всю работу за вас.Он только для заголовков, поэтому, если вы уже используете Boost, для вас нет новой зависимости.
Этот файл отвечает за генерацию оператора switch.Короче говоря, у него есть две альтернативные реализации.В первом (строки 72-90) используется рекурсивный шаблон visitation_impl_step
, который работает как функция факториала, которую вы могли видеть в качестве примера метапрограммирования шаблона.Неспециализированный шаблон рекурсивно вызывает следующий в списке (typename mpl::next<Iter>::type
).Результирующий код после развертывания всех шаблонов выглядит как серия функций function0, function1, & c.например:
result_type functionN(variant vnt, visitor vr) {
if (v.which == N)
return vr(static_cast<Nth type>(vnt.value));
else
functionN-1(vnt, vr);
}
Вторая реализация (строки 193-285) использует магическую библиотеку препроцессора Boost.PP для генерации оператора switch точно так же, как вы хотите, с таким количеством случаев, как boost::variant
может иметьТело каждого случая - это вызов функции шаблона (строки 120-185), которая генерирует вызов для посетителя N-го типа.Большая сложность в этой реализации возникает из-за необходимости беспокоиться о резервном копировании значения внутри variant
, чтобы сохранить гарантию сильных исключений, если посетитель или любой задействованный конструктор сгенерирует.
Даже если вы решитесделайте это по-другому, я рекомендую прочитать и понять исходный код Boost.Variant, как учебное упражнение.Это переопределит ваши идеи о том, что возможно (и что разумно) в C ++!