Комплексное использование шаблона в C ++ - PullRequest
0 голосов
/ 02 апреля 2020

Я сталкиваюсь с фрагментом кода о шаблоне:

unroller.h

template <int It, int End> struct unroller {
    template <typename Action> static void step(const Action &action) {
        action(std::integral_constant<int, It>());
        unroller<It + 1, End>::step(action);
    }
};

template <int End> struct unroller<End, End> {
    template <typename Action> static void step(const Action &) {}
};

фрагмент кода, который показывает, как он вызывается:

constexpr int NUM_ROWS = 2;
constexpr int NUM_COLS = 2;
int input_idx = 0;
for (int pass = 0; pass < num_passes; pass++) {
    unroller<0, NUM_ROWS>::step([&input_idx, input_accessor](auto i_idx) {
    constexpr int i = i_idx.value;

        unroller<0, NUM_COLS>::step([&input_idx, input_accessor](auto j_idx) {
        constexpr int j = j_idx.value;

            ProducerToConsumerPipeMatrix::pipe_at<i, j>::write(input_accessor[input_idx++]);
        });
    });
} 

Вопрос:

  1. template <typename Action> static void step(const Action &action) это шаблон функции?
  2. что такое action(std::integral_constant<int,It>());? Я думал, что действие передается по ссылке. Тем не менее, я не совсем понимаю.
  3. Я не понимаю, как это вызывает unroller<0, NUM_ROWS>::step([&input_idx, input_accessor](autoi_idx). Насколько я понимаю, в угловых скобках <> должны быть типы данных. В этом случае это передать значение. Кроме того, что такое :: шаг? Тогда, почему он может передать 2 аргумента в шаге (...)>

Я новичок в c ++. Может кто-нибудь объяснить простым способом?

Ответы [ 2 ]

0 голосов
/ 02 апреля 2020

Я новичок в c ++. Может кто-нибудь объяснить простым способом?

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

  1. template stati c void step (const Action & action) является шаблоном функции?

Да, функция, в которой Action является параметр.

что такое действие (std :: integra_constant ()) ;? Я думал, что действие передается по ссылке. Тем не менее, я не совсем понимаю.

Общая идея unroller состоит в том, чтобы развернуть все oop. Это позволяет автоматически генерировать последовательность вызовов чего-то вроде:

action(0);
action(1);
action(2);
...
action(NUM_ROWS-1);

action - это параметр для любой функции, которая может получить значение int. Используемая здесь функция:

[&input_idx, input_accessor](auto i_idx) {
    constexpr int i = i_idx.value;
    unroller<0, NUM_COLS>::step([&input_idx, input_accessor](auto j_idx) {
        constexpr int j = j_idx.value;
        ProducerToConsumerPipeMatrix::pipe_at<i,j>::write(input_accessor[input_idx++]);
    }
}

, которая сама использует развертывание! Похоже, это разворачивает вычисления на двухмерных матричных элементах. Эти функции называются лямбда-выражениями, анонимные функции вы предпочитаете. Тогда вы находитесь в сфере функционального программирования.

Я не понимаю, как это вызывает unroller<0, NUM_ROWS>::step([&input_idx, input_accessor](autoi_idx). Насколько я понимаю, в угловых скобках <> должны быть типы данных. В этом случае это передать значение. Кроме того, что такое :: шаг? Тогда, почему он может передавать 2 аргумента в шаге (...)>

Параметры шаблона могут быть типами, но также могут быть значения различного вида ... unroller является типом шаблона это принимает два аргумента: <int It, int End>. It и End набираются как int s, а не class или typename (как это имеет место с Action).

0 голосов
/ 02 апреля 2020

Я думаю, вам может понадобиться начать изучение шаблонов с самого начала.

  1. Да. Это типичный шаблон функции
  2. Нет, он передается по значению, по крайней мере, в вашем примере передается по значению.
[&input_idx, input_accessor](auto j_idx) {
        constexpr int j = j_idx.value;

            ProducerToConsumerPipeMatrix::pipe_at<i, j>::write(input_accessor[input_idx++]);
        });

эта лямбда передается в функцию более высокого порядка step в качестве параметра, позже он получит временное значение std::integral_constant<int, It> prvalue в качестве параметра лямбды.

std::integral_constant<int,It>() создает временный объект std::integral_constant<int, It>, см. Это: https://en.cppreference.com/w/cpp/types/integral_constant

Это не два аргумента, это лямбда-захват, смотрите это: https://en.cppreference.com/w/cpp/language/lambda

параметры шаблона не должны быть типами, смотрите это: https://en.cppreference.com/w/cpp/language/templates#Syntax

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