我想写一个binary indexed array
,
使用两个非类型的默认模板参数op
和identity
。
需要检查op(identity,identity) == identity
。
我的问题是,
op
,我目前的解决方案无法编译。
‘class std::function<T(T, T)>’ is not a valid type for a template non-type parameter
op(identity,identity) == identity
,目前我无法验证,因为第1步失败,可能是static_assert
?所以目前我使用下面的解决方法,但后来我无法指定op
,例如std::multiplies<int>
。
谁能告诉我如何实现目标?
#include <vector>
#include <functional>
// template <typename T = int, std::function<T(T,T)> op = std::plus<T>(), const T identity = T()>
template <typename T = int, const T identity = T()> // currently workaround
class BIT { // binary indexed array
const std::function<T(T,T)> op = std::plus<T>(); // currently workaround
public:
BIT(std::vector<T> value) : value(value), prefixSum(value.size() + 1, identity) {
for (size_t i = 1; i < prefixSum.size(); ++i) {
incrementNodeByValue(i, value[i-1]);
}
// print(prefixSum,"prefixSum");
}
T getSum(size_t i) {
auto sum = identity;
while (i) {
sum = op(sum, prefixSum(i));
i = firstSmallerAncestor(i);
}
return sum;
}
void incrementNodeByValue(size_t i, T x) {
while (i < prefixSum.size()) {
prefixSum[i] = op(prefixSum[i], x);
i = firstLargerAncestor(i);
}
}
private:
inline size_t firstLargerAncestor(size_t node) { return node + (node & -node); }
inline size_t firstSmallerAncestor(size_t node) { return node & (node - 1); }
std::vector<T> value;
std::vector<T> prefixSum;
};
int main() {
auto vec = std::vector<int> {5,1,15,11,52,28,0};
auto bit = BIT<>(vec);
}
答案 0 :(得分:3)
在这里使用std::function
是一种浪费,似乎是您混淆的根源。
请注意,模板只能在类型名称和整数类型的值(char
,int
,long
等)上进行参数化。在这里,您尝试参数化std::function
实例化的值,该实例化不是整数类型。也就是说,在这种情况下,您实际上不需要对值进行参数化。
因为构造函数不接受初始化op
成员变量的参数也不能通过接口访问,所以我认为可以安全地假设运算符在编译时是已知的,保证是不可变的,并且默认可构造。
因此,我将op
成员声明为名为operation
的参数类型。
#include <functional>
#include <vector>
template< typename T = int,
typename operation = std::plus<T>,
const T identity = T() >
class BIT {
const operation op = operation();
static_assert( operation()(identity, identity) == identity );
std::vector<T> value;
std::vector<T> prefixSum;
inline size_t firstLargerAncestor(size_t node) { return node + (node & -node); }
inline size_t firstSmallerAncestor(size_t node) { return node & (node - 1); }
public:
BIT(std::vector<T> value) :
value(value),
prefixSum(value.size() + 1, identity) {
for (size_t i = 1; i < prefixSum.size(); ++i) {
incrementNodeByValue(i, value[i-1]);
}
}
T getSum(size_t i) {
auto sum = identity;
while (i) {
sum = op(sum, prefixSum(i));
i = firstSmallerAncestor(i);
}
return sum;
}
void incrementNodeByValue(size_t i, T x) {
while (i < prefixSum.size()) {
prefixSum[i] = op(prefixSum[i], x);
i = firstLargerAncestor(i);
}
}
};
作为一个注释,您可能希望在其他位置定义identity
模板以在操作和值类型上进行参数化,以在此处默认第三个参数。在实例化过程中,似乎你几乎总是定义所有三个参数。