Возможно ли иметь цикл for во время компиляции со временем выполнения или даже с ограничением по времени компиляции в c ++ 11? - PullRequest
0 голосов
/ 17 октября 2018

Я хотел бы знать, возможно ли иметь цикл for во время компиляции со временем выполнения или даже с условием ограничения времени компиляции в c ++ 11?Я начинаю с глупой попытки выяснить, что мне нужно.

for (uint32_t i = 0; i < n; ++i)
  {
    templated_func<i>();
  }

рассмотрим, у меня есть класс с закрытой переменной-членом n, и я хочу вызвать функцию шаблона с другим числом, которое повторяется от 0к (для случая ограничения времени выполнения) я изучал «Шаблонное метапрограммирование» и «Constexpr If» (c ++ 17), но я не получил никаких результатов, кто-нибудь может мне помочь?

Ответы [ 3 ]

0 голосов
/ 17 октября 2018

Я хотел бы знать, возможно ли иметь цикл for во время компиляции с условием времени выполнения или даже с ограничением времени компиляции в c ++ 11

Я не знаюразумный способ иметь такой цикл с условием времени выполнения.

с условием времени компиляции ... Если вы можете использовать хотя бы C ++ 14, вы можете использовать решение, основанное на std::integer_sequence / std::make_integer_sequence (см. ответ Калет) или, может быть, std::index_sequence / std::make_index_sequence (чуть более искусственно).

Если вы ограничены в C ++ 11, вы можете создать суррогат для std::index_sequence /std::make_index_sequence или вы можете создать рекурсивную структуру шаблона со статической функцией (к сожалению, вы можете частично специализировать функцию шаблона, но вы можете частично специализировать классы и структуры).

Я имею в виду ... что-то следующее

template <std::size_t I, std::size_t Top>
struct for_loop
 {
   static void func ()
    {
      templated_func<I>();
      for_loop<I+1u, Top>::func();
    }
 };

template <std::size_t I>
struct for_loop<I, I>
 { static void func () { } };

, который вы можете вызвать

constexpr auto n = 10u;

for_loop<0, n>::func();

, если хотите позвонить templated_func() со значениями от нуля до n-1u.

К сожалению, это решение рекурсивное, поэтому вы можетеесть проблемы с ограничениями рекурсии компиляторов.То есть ... работает, только если n не высоко.

0 голосов
/ 17 октября 2018

Как вы сказали, у вас был только C ++ 11, тогда у вас не будет std :: make_index_sequence, и вам придется его предоставить.Кроме того, выражение сгиба в ответе Калет недоступно до C ++ 17.

Обеспечение собственной реализации index_sequence и выражения сгиба в c ++ 11 может быть выполнено следующим образом:

#include <iostream>

template <size_t... Is>
struct index_sequence{};

namespace detail {
    template <size_t I,size_t...Is>
    struct make_index_sequence_impl : make_index_sequence_impl<I-1,I,Is...> {};

    template <size_t...Is>
    struct make_index_sequence_impl<0,Is...>
    {
        using type = index_sequence<0,Is...>;
    };
}

template<size_t N>
using make_index_sequence = typename detail::make_index_sequence_impl<N>::type;


template<size_t I>
void templated_func()
{
    std::cout << "templated_func" << I << std::endl;
}

template <size_t... Is>
void call_templated_func(index_sequence< Is...>)
{
    using do_ = int[];
    do_ {0,(templated_func<Is>(),0)...,0};
}

int main()
{
    call_templated_func(make_index_sequence< 10>());
    return 0;
}

По сути, это то же самое, что и ответ @Caleth, но с предоставленными недостающими битами, и он будет скомпилирован на C ++ 11.

demo

демо на компиляторе c ++ 11

0 голосов
/ 17 октября 2018

У вас не может быть цикла for, но вы можете вызвать N лотов templated_func

namespace detail {
    template <template<uint32_t> class F, uint32_t... Is>
    void static_for_impl(std::integer_sequence<uint32_t, Is...>)
    {
        F<Is>{}()...;
    }
}

template <template<uint32_t> class F, uint32_t N>
void static_for()
{
    detail::static_for_impl<F>(std::make_integer_sequence<uint32_t, N>{}); 
}

template <uint32_t I>
struct templated_caller
{
    void operator()() { templated_func<I>(); }
}

int main()
{
    static_for<templated_caller, 10>();
    return 0;
}

Обратите внимание, что это более общий вопрос, чем вы просили.Вы можете упростить его до

template <uint32_t... Is>
void call_templated_func(std::integer_sequence<uint32_t, Is...>)
{
    templated_func<Is>()...;
}

int main()
{
    call_templated_func(std::make_integer_sequence<uint32_t, N>{});
    return 0;
}

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

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