C++模板参数推理

C++ template parameter inference

本文关键字:推理 参数 C++      更新时间:2023-10-16

作为练习,我尝试使用模板编写数组实现,但使用函数指针作为模板参数。每次为数组编制索引时都会调用此函数。

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;
}

main函数中的最后一个数组声明是我想要的,其中 checkIndex 的模板参数与数组中以前的模板参数匹配。但是这不会编译(使用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

有没有办法获得所需的结果,其中提供的函数的模板参数是从其他参数推断出来的?

可能不适用于您的实际用例,但我建议使用一个可调用的对象,其中包含一个执行检查的函数:

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;
}

魔杖盒示例


我们来分析一下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

.template消除歧义语法是必需的,因为编译器不知道check的含义 - 它可能是一个字段,该行可以解释为:

fnIndex{}.check < size > (index)

其中<小于运算符>大于运算符(index)是表达式。

使用 .template 告诉编译器我们要调用模板方法。