gpt4 book ai didi

c++ - 我可以使用模板来控制代码块并确保它不会爆炸吗?

转载 作者:行者123 更新时间:2023-11-28 04:38:03 25 4
gpt4 key购买 nike

我正在编写一个函数,用 C++ 对大量表数据进行一些计算。该函数应接受“指令”列表以指定要计算的内容。

例如表格可以是这样的

| A | B | C ||---|---|---|| 1 | 2 | 4 || 2 | 3 | 5 || 3 | 5 | 6 ||...........|

I am trying to build a function that look like this

std::vector<int> compute(const Table& input, const std::vector<MetricsEnum>& metrics)
{
std::vector<int> result;
result.reserve(some heuristic number I put in);
for(const auto& row: input)
{
if(std::find(metrics.begin(), metrics.end(), Metrics1) != metrics.end())
{
result.push_back(row[A] + row[B]);
}
if(std::find(metrics.begin(), metrics.end(), Metrics2) != metrics.end())
{
result.push_back(row[A] - row[B]);
}
// this list goes for about 5 or 6 metrics for now, but later I plan to add more
}
}

所以我遇到的问题是,显然输入有很多行,现在在循环内执行 if 语句对我来说更像是一种奢侈。我希望能够使用模板在编译时生成一堆函数,并根据我在运行时想要的指标选择其中一个。在线的东西:

template <bool metrics1, bool metrics2 ...>
std::vector compute(const Table& input>
{
...
if(metrics1)
{
result.push_back(row[A] + row[B]);
}
if(metrics2)
{
result.push_back(row[A] - row[B]);
}
...
}

但是这里有几个问题我觉得很难解决:

  1. 我不确定如何在这里实现我的想法。你能给我举一些例子吗?我有一种模糊的感觉,即 C++17 中的 if constexpr 对我有好处。但不幸的是,我仍然在 C++11 的土地上,不得不在这里停留一段时间。
  2. 更重要的是,我的想法是否值得实现?据我了解,C++ 编译器将在编译时生成 2^n 个函数,其中 n 是指标数。目前这个数字相对较小,但函数的数量呈指数增长,我很确定 n 会在某个时候大于 10。所以我的问题是我是否应该担心我的二进制文件在这种情况下会爆炸?

最佳答案

忘记在编译时尝试做事,并且(现在)忘记性能。弄清楚实际功能后,优化该部​​分。

在这种情况下,您 [似乎试图] 做的是,对于表中的每一行,对两个预先确定的索引进行一系列计算,然后将结果推送到一个 vector 中。我不知道 AB 是如何获得它们的值的,所以我的解决方案不会涉及它们。

我的第一个建议是将整个事情组织成一个可以调用的函数表:

//Replace all instances of 'int' with whatever type you're using
std::vector<int> compute(const Table& input, const std::vector<MetricsEnum>& metrics)
{
typedef int (*func_ptr_type)(int,int);
//I'm assuming MetricsEnum is a literal enum type, convertible to an integer.
static const std::array<func_ptr_type, 6> functions{
+[](int a, int b) {return a + b;},
+[](int a, int b) {return a - b;},
+[](int a, int b) {return a * b;},
+[](int a, int b) {return a / b;},
+[](int a, int b) {return a << b;},
+[](int a, int b) {return a >> b;}
//Add more and increase the size of the array, as needed
};
std::vector<int> result;
//Don't do this; let the compiler and allocator do their jobs
//result.reserver(some heuristic number I put in);
for(const auto& row: input)
{
for(MetricsEnum metricsEnum : metrics) {
result.emplace_back(functions.at(size_t(metrics))(row[A], row[B]));
}
}
return result;
}

在这种形式下,可以更容易地看出代码的用途,而且我们还可以更轻松地组织整个事情。

下一步将是完全消除数组,并使该函数成为 MetricsEnum 类型行为的核心部分,无论它是什么。

template<typename T>
class MetricsEnum {
public:
enum class Type {
add, subtract, multiply, divide, shift_left, shift_right
};
constexpr MetricsEnum(Type type) : type(type) {}

constexpr T operator()(T a, T b) const {
switch(type) {
case Type::add: return a + b;
case Type::subtract: return a - b;
case Type::multiply: return a * b;
case Type::divide: return a / b;
case Type::shift_left: return a << b;
case Type::shift_right: return a >> b;
default: return {};
}
}
private:
Type type;
};

std::vector<int> compute(const Table& input, const std::vector<MetricsEnum<int>>& metrics)
{
std::vector<int> result;
for(const auto& row: input)
{
for(auto const& metricsEnum : metrics) {
result.emplace_back(metricsEnum(row[A], row[B]));
}
}
return result;
}

还有许多其他方法可以处理这个问题(多态性浮现在脑海中......);这对我来说是最直观的。

关于c++ - 我可以使用模板来控制代码块并确保它不会爆炸吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50864983/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com