Генерация кода, создающего экземпляр шаблона функции с разными аргументами

Учитывая следующий код:

#include <iostream>

template <int X, int Y>
int foo(int v) // dummy parameter
{
return v * X + v / Y; // dummy calculation
}

int main()
{
// x, y, v are only known at runtime
int x = 4;
int y = 6;
int v = 3;

int result = 0;

if (x == 1 && y == 1) result = foo<1, 1>(v);
if (x == 1 && y == 3) result = foo<1, 3>(v);
if (x == 5 && y == 1) result = foo<5, 1>(v);
if (x == 4 && y == 6) result = foo<4, 6>(v);
if (x == 8 && y == 4) result = foo<8, 4>(v);
// ...

std::cout << result << std::endl;
}

Я хотел бы создать экземпляр foo для разных комбинаций X а также Y как показано в if каскад в main,

Это, однако, может стать довольно уродливым (долго). Есть ли возможность использовать C ++ 14 (например, с помощью препроцессора) для генерации этого кода с учетом списка необходимой комбинации?

0

Решение

Генерировать код и экземпляры для известных пар x и y легко, если это именно то, что вы хотите.

#define XYLIST \
X(1,1)\
X(1,3)\
X(5,1)\
X(4,6)\
X(8,4)
// etc.

#define X(X1, Y1) \
if (X1 == 1 && Y1 == 1) result = foo<X1, Y1>(v); else

XYLIST
{ throw "failed"; }

#undef X

Добавлен «else», так как не должно быть двух одинаковых строк. И «бросок» в конце, чтобы закончить остальной каскад.

1

Другие решения

Это версия с использованием рекурсии.

#include <iostream>
#include <utility>
#include <stdexcept>

template <int X, int Y>
int foo(int v) // dummy parameter
{
return v * X + v / Y; // dummy calculation
}

template <std::size_t index = 0>
int foo(int x, int y, int v) {
constexpr std::pair<int, int> numbers[] = {{1, 1}, {1, 3}, {5, 1}, {4, 6}, {8, 4}};
if constexpr (index < sizeof numbers / sizeof *numbers) {
if (numbers[index].first == x && numbers[index].second == y) {
return foo<numbers[index].first, numbers[index].second>(v);
}
return foo<index + 1>(x, y, v);
} else { //no match
throw std::runtime_error("No matching pair found");
}
}

int main() {
// x, y, v are only known at runtime
int x = 4;
int y = 6;
int v = 3;

int result = foo(x, y, v);

std::cout << result << std::endl;
}

Если у вас нет C ++ 17, вы можете заменить if constexpr с диспетчеризацией тегов. И clang, и gcc могут оптимизировать код, начиная с -O1.

3

Вы можете конвертировать их в постоянные выражения. Если значения incase известны заранее

#include <iostream>

template <int X, int Y>
int foo(int v) // dummy parameter
{
return v * X + v / Y; // dummy calculation
}

int main()
{
// x, y, v are only known at runtime
const int x = 4;
const int y = 6;
int v = 3;

int result = 0;

result = foo<x, y>(v);std::cout << result << std::endl;
}

Тем не мение, Шаблоны — это не алгоритм, который нужно выполнить, а макросы, которые нужно развернуть для создания кода.
Я бы не рекомендовал использовать шаблон для того же тип данных , в этом случае вы используете только int. Следовательно, шаблон не особенно требуется согласно стандартам кодирования.

Передайте эти значения в самой функции.

Способ 1: Если все у вас есть целые числа.

int foo(int v, int X, int Y) // dummy parameter
{
return v * X + v / Y; // dummy calculation
}
int main()
{
// x, y, v are only known at runtime
int x = 4;
int y = 6;
int v = 3;

int result = 0;

result = foo(v,x,y);
}

Способ 2: Если что-то может быть передано, то есть дважды тип данных ,и т.п.

template <typename T>
T foo(int v, T Y, T Y) // dummy parameter
{
return v * X + v / Y; // dummy calculation
}
0
По вопросам рекламы [email protected]