ПОМЕЩЕНИЕ:
Немного поиграв с вариативными шаблонами, я понял, что достижение чего-либо, что немного выходит за рамки тривиальных задач метапрограммирования, скоро становится довольно громоздким. В частности, я решил, что хочу выполнить общие операции над пакетом аргументов, такие как итерация, разделение, цикл в стиле std::for_each
и т.д.
После просмотра этой лекции Андрея Александреску из С++ и Beyond 2012 о желательности static if
в С++ (конструкция, заимствованная из D Язык программирования) У меня было ощущение, что какой-то static for
тоже будет полезен - и я чувствую больше этих static
конструкции могут принести пользу.
Итак, я начал задаваться вопросом, есть ли способ достичь чего-то вроде этого для пакетов аргументов функции вариационного шаблона (псевдокод):
template<typename... Ts>
void my_function(Ts&&... args)
{
static for (int i = 0; i < sizeof...(args); i++) // PSEUDO-CODE!
{
foo(nth_value_of<i>(args));
}
}
Что бы перевести во время компиляции в нечто подобное:
template<typename... Ts>
void my_function(Ts&&... args)
{
foo(nth_value_of<0>(args));
foo(nth_value_of<1>(args));
// ...
foo(nth_value_of<sizeof...(args) - 1>(args));
}
В принципе, static_for
обеспечит еще более сложную обработку:
template<typename... Ts>
void foo(Ts&&... args)
{
constexpr s = sizeof...(args);
static for (int i = 0; i < s / 2; i++)
{
// Do something
foo(nth_value_of<i>(args));
}
static for (int i = s / 2; i < s; i++)
{
// Do something different
bar(nth_value_of<i>(args));
}
}
Или для более выразительной идиомы, подобной этой:
template<typename... Ts>
void foo(Ts&&... args)
{
static for_each (auto&& x : args)
{
foo(x);
}
}
СООТВЕТСТВУЮЩАЯ РАБОТА:
Я сделал несколько поисков в Интернете и узнал, что что-то действительно существует:
- В этой ссылке описано, как преобразовать пакет параметров в вектор Boost.MPL, но это происходит только наполовину (если не меньше ) к цели;
- этот вопрос на SO, похоже, вызывает аналогичную и слегка связанную функцию метапрограммирования (разделение пакета аргументов на две половины) - на самом деле есть несколько вопросов на SO, которые, похоже, связаны с этой проблемой, но ни один из ответов, которые я прочитал, не удовлетворяет им ИМХО;
- Boost.Fusion определяет алгоритмы преобразования пакета аргументов в кортеж, но я бы предпочел:
- не создавать ненужные временные файлы для хранения аргументов, которые могут (и должны быть) отлично перенаправлены на некоторые общие алгоритмы;
- иметь небольшую автономную библиотеку, чтобы сделать это, в то время как Boost.Fusion скорее всего будет включать в себя больше материала, чем это необходимо для решения этой проблемы.
Вопрос:
Существует ли относительно простой способ, возможно, через некоторое метапрограммирование шаблонов, чтобы достичь того, что я ищу, не допуская ограничений существующих подходов?