生成代码以实例化具有不同参数的函数模板
Generate code instantiating a function template with different arguments
给定以下代码:
#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;
}
我想为 X
和 Y
的不同组合实例化 foo
,如 main
中的 if
级联所示。
然而,这可能会变得非常丑陋(长)。是否有可能使用 C++14(例如,通过使用预处理器)在给定所需组合列表的情况下生成此代码?
如果这正是您想要的,那么为已知的 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",因为不应有相同的两行。最后还有一个 "throw" 来完成 else 级联。
您可以将它们转换为常量表达式。如果柜面值事先已知
#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。因此,根据编码标准,并不特别需要模板。
在函数本身中传递这些值。
方法一:如果你只有整数。
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);
}
方法二:如果可以传递任何东西,即double data-type等
template <typename T>
T foo(int v, T Y, T Y) // dummy parameter
{
return v * X + v / Y; // dummy calculation
}
这是一个使用递归的版本。
#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
替换为标签调度。 Both clang and gcc manage to optimize out the code starting at -O1.
给定以下代码:
#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;
}
我想为 X
和 Y
的不同组合实例化 foo
,如 main
中的 if
级联所示。
然而,这可能会变得非常丑陋(长)。是否有可能使用 C++14(例如,通过使用预处理器)在给定所需组合列表的情况下生成此代码?
如果这正是您想要的,那么为已知的 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",因为不应有相同的两行。最后还有一个 "throw" 来完成 else 级联。
您可以将它们转换为常量表达式。如果柜面值事先已知
#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。因此,根据编码标准,并不特别需要模板。
在函数本身中传递这些值。
方法一:如果你只有整数。
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);
}
方法二:如果可以传递任何东西,即double data-type等
template <typename T>
T foo(int v, T Y, T Y) // dummy parameter
{
return v * X + v / Y; // dummy calculation
}
这是一个使用递归的版本。
#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
替换为标签调度。 Both clang and gcc manage to optimize out the code starting at -O1.