Clang: развертка цикла для конкретного цикла

Есть ли способ сказать clang, чтобы развернуть конкретный цикл?


Googling для ответа дает мне параметры командной строки, которые влияют на весь компилятор, а не на один цикл.


Аналогичный вопрос для GCC --- Сообщить gcc о том, чтобы развернуть цикл --- но предоставленный там ответ не работает с clang.

Вариант 1 предложил там:

#pragma GCC optimize ("unroll-loops")

кажется, молча игнорируется. Фактически

#pragma GCC akjhdfkjahsdkjfhskdfhd

также игнорируется.

Вариант 2:

__attribute__((optimize("unroll-loops")))

выводится предупреждение:

warning: unknown attribute 'optimize' ignored [-Wattributes]

Обновление

joshuanapoli обеспечивает хорошее решение для итерации с помощью метапрограммирования шаблонов и С++ 11 без создания цикла. Конструкция будет разрешена во время компиляции, что приведет к многократно наложенному телу. Хотя это не совсем ответ на вопрос, он по сути достигает того же.

Вот почему я принимаю ответ. Однако, если вам известно, как использовать стандартный цикл C (for, while) и заставить его развернуть - пожалуйста, поделитесь знаниями с нами!

Ответ 1

Для программы на С++ вы можете разворачивать циклы внутри языка. Вам не нужно будет определять параметры, специфичные для компилятора. Например,

#include <cstddef>
#include <iostream>

template<std::size_t N, typename FunctionType, std::size_t I>
class repeat_t
{
public:
  repeat_t(FunctionType function) : function_(function) {}
  FunctionType operator()()
  {
    function_(I);
    return repeat_t<N,FunctionType,I+1>(function_)();
  }
private:
  FunctionType function_;
};

template<std::size_t N, typename FunctionType>
class repeat_t<N,FunctionType,N>
{
public:
  repeat_t(FunctionType function) : function_(function) {}
  FunctionType operator()() { return function_; }
private:
  FunctionType function_;
};

template<std::size_t N, typename FunctionType>
repeat_t<N,FunctionType,0> repeat(FunctionType function)
{
  return repeat_t<N,FunctionType,0>(function);
}

void loop_function(std::size_t index)
{
  std::cout << index << std::endl;
}

int main(int argc, char** argv)
{
  repeat<10>(loop_function)();
  return 0;
}

Пример со сложной функцией цикла

template<typename T, T V1>
struct sum_t
{
  sum_t(T v2) : v2_(v2) {}
  void operator()(std::size_t) { v2_ += V1; }
  T result() const { return v2_; }
private:
  T v2_;
};

int main(int argc, char* argv[])
{
  typedef sum_t<int,2> add_two;
  std::cout << repeat<4>(add_two(3))().result() << std::endl;
  return 0;
}
// output is 11 (3+2+2+2+2)

Использование замыкания вместо явного объекта функции

int main(int argc, char* argv[])
{
  int accumulator{3};
  repeat<4>( [&](std::size_t)
  {
    accumulator += 2;
  })();
  std::cout << accumulator << std::endl;
}