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

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

Ответ 1

Лично я думаю, что Boost.Spirit - довольно удивительный пример метапрограммирования. Это полный генератор синтаксического анализатора, который позволяет вам выражать грамматику с использованием синтаксиса C++.

Ответ 2

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

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

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

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

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

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

Это быстро выявило все места, которые я неявно приписал IFoo.

Ответ 3

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

metatrace example

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

Ответ 4

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

Ответ 5

Самый классный пример метапрограммирования: использование компилятора для вычисления списка простых чисел. Не очень практично, но впечатляюще.

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

Ответ 7

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

Ответ 8

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

Ответ 9

BOOST_FOREACH

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

(Примечание: встроенная поддержка циклических и статических утверждений на основе диапазона введена в С++ 11)

Ответ 10

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

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

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

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