作为练习,我试图使用模板编写数组实现,但使用函数指针作为模板参数.每次对数组进行索引时都会调用此函数.
template<typename T, int size>
using Array_fnIndex = void (*)(int index);
template<typename T, int size, typename Array_fnIndex<T, size> fnIndex>
struct Array {
T data[size];
T& operator[](int index) {
fnIndex(index);
return data[index];
}
};
// example index function
template<typename T, int size>
void checkIndex(int index) {
assert(index < size);
}
int main() {
Array<int, 10, checkIndex<int, 10>> a; // this works
Array<int, 10, checkIndex<int, 11>> b; // this also works, not what I want
Array<int, 10, checkIndex> c; // this doesn't work, but what I want
return 0;
}
Run Code Online (Sandbox Code Playgroud)
main函数中的最后一个数组声明是我想要的,其中checkIndex的模板参数与Array中的先前模板参数匹配.但是这不能编译(使用Microsoft编译器).我收到以下错误:
error C2440: 'specialization': cannot convert from 'void (__cdecl *)(uint)' to 'void (__cdecl *)(uint)'
note: None of the functions with this name in scope match the target type
Run Code Online (Sandbox Code Playgroud)
有没有办法获得所需的结果,其中提供的函数的模板参数从其他参数推断?
可能不适用于您的实际用例,但我建议一个包含执行检查的函数的可调用对象:
template<typename T, int size, typename fnIndex>
struct Array {
T data[size];
T& operator[](int index) {
fnIndex{}.template check<size>(index);
return data[index];
}
};
struct checkIndex {
template<int size>
void check(int index) {
assert(index < size);
}
};
int main() {
Array<int, 10, checkIndex> c;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我们来分析一下fnIndex{}.template check<size>(index):
fnIndex{} // make a temporary object of type `fnIndex`
.template check<size>(index) // call its `check` method using `size`
// as a template argument and `index` as
// as a function argument
Run Code Online (Sandbox Code Playgroud)
的.template,因为编译器不知道什么歧义的语法是必需的check手段-它可以是一个字段和行可以解释为:
fnIndex{}.check < size > (index)
其中<是小于运算符,>是操作者大于-,并且(index)是一个表达式.
使用.template告诉编译器我们要调用模板方法.