Какие самые крутые примеры метапрограммирования вы видели в C++? [закрытый]

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

Подробнее: https://stackoverflow.com/faq


какие самые крутые примеры метапрограммирования вы видели в C++?
Каковы некоторые практические применения метапрограммирования, которые вы видели в C++?

10 ответов



наиболее практичным использованием метапрограммирования является превращение ошибки времени выполнения в ошибку времени компиляции.

пример: позволяет вызвать интерфейс IFoo. Одна из моих программ имела дело с COM-объектом, который имел несколько путей к IFoo (очень сложная иерархия наследования). К сожалению, базовая реализация COM-объекта не понимала, что у них есть несколько путей к IFoo. Они предполагали, что это всегда был самый левый. Таким образом, внутри их кода следующий шаблон был очень common

   void SomeMethod(IFoo* pFoo) {
        CFooImpl *p = (CFooImpl)pFoo;
   }

второй IFoo, хотя вызвал результирующий указатель "p", чтобы быть полностью недействительным (множественное наследование опасно).

долгосрочное решение состояло в том, чтобы владелец COM-объекта исправил эту проблему. Короткий срок, хотя мне нужно было убедиться, что я всегда возвращал правильный IFoo. Я мог бы гарантировать, что у меня есть соответствующий IFoo, используя QI и избегая любых неявных бросков в IFoo. Поэтому я создал новую реализацию CComPtr и добавил после переопределения метода equal.

template <typename T>
CComPtr<T>& operator=(const T* pT)  { 
// CComPTr Assign logic
}
template <>
CComPtr<IFoo> operator=<IFoo>(const IFoo* pT) {
  COMPILE_ERROR();
}

это быстро показало каждое место, которое я неявно бросил в IFoo.


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


Не практического использования (за исключением, возможно, для тестирования компилятора), но metatrace-это трассировщик лучей в стиле Whitted (т. е. рекурсивный и детерминированный), который генерирует изображения, подобные тем, которые во время компиляции:

metatrace example

некоторые более сложные части код можно увидеть в fixp.hh, который имеет реализацию фиксированной точки sqrt с использованием метода Heron, или сфере.hh который показывает пересечение луча / сферы расчет.



самый крутой пример метапрограммирования: обман компилятора в вычислении списка простых чисел. Не очень практично, но эффектно.

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


Я бы сказал, Boost.Лямбда, Толчок.Функции и Boost.Bind и то, как они все работают вместе. Они обеспечивают действительно гладкий интерфейс и делают функциональное программирование максимально простым на языке, который на самом деле не был создан для него.


luabind-довольно классный практический пример, довольно хорошая привязка dsl для привязки классов C++ к lua


BOOST_FOREACH

статическое утверждение (повышает версию здесь)


Я задал вопрос не так давно: C++ знание среды выполнения классов и ответ, который я получил от пользователя StackOverflow "Denice", был URL-адресом веб-сайта Meatspace: Регистрация класса среды выполнения C++.

Я думаю, что это действительно классный способ использовать шаблоны и создавать экземпляры объектов, которые являются производными от базового класса, так что когда у меня есть 10 файлов c++, они могут просто добавить AUTO_REGISTER_BASE () внизу, и когда все будет сделано и связанные, только те классы/файлы, которые сделали это, будут зарегистрированы, поэтому во время выполнения вы можете переключаться между различными классами, которые доступны, а те, которые недоступны, не зарегистрированы и, следовательно, не могут быть случайно вызваны.

существует много различных зависящих от ОС способов уведомления о событиях (select (), kqueue (), /dev/epoll, Solaris имеет свою собственную вещь, poll ()), и мне нужен способ, чтобы все файлы классов существовали в Каталоге, но в зависимости от того, какая ОС Makefile был запущен, он будет компилировать только определенные. Мне нужен был способ узнать во время выполнения, какие из них были доступны, и у программиста, использующего библиотеку, есть способ выбрать их предпочтения, однако, если он был недоступен, просто используйте тот, который имел наиболее логичный смысл для платформы (у каждого из них есть веса, назначенные им).

код выше помог мне достичь этой цели, с некоторыми здоровенными изменениями, но это помогло мне тем не менее!