2017-01-09 141 views
7

作爲一個練習,我正在嘗試使用模板編寫數組實現,但函數指針作爲模板參數。每次數組獲得索引時都會調用該函數。C++模板參數推理

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 

有什麼辦法來得到期望的結果,其中用於提供的函數模板參數也會從其他參數推斷?

+0

您的實際代碼中是否需要'checkIndex'上的模板? – AndyG

+2

另外,您無法在任何地方傳遞模板函數指針......它只是不存在。在你想傳遞模板函數的地方,你必須實例化它。這就是爲什麼Vittorio將你的函數變成結構體的原因。 – AndyG

回答

6

可能並不適用於您的實際使用情況,但我建議調用對象包含該檢查的功能:

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

wandbox example


我們來分析一下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 

是因爲編譯器不知道什麼check意味着.template歧義語法是必需的 - 這可能是一個字段和行可以解釋爲:

fnIndex{}.check <size> (index)

其中<小於操作>大於運算符,並且(index)是表達式。

使用.template告訴編譯器我們要調用模板方法。

+0

我嘗試了你的wandbox示例,但它沒有編譯[wandbox示例](http://melpon.org/wandbox/permlink/X3k1Up5CKsejqI7q) – toteload

+0

@toteload:whoops,[fixed](http://melpon.org/ wandbox/permlink/LD2hF7Lp4BUHR23V)。我在這臺機器上的wandbox上有一個奇怪的緩存問題... –

+0

不錯!我學到了一些新東西。感謝幫助! – toteload