我有一個函數,它接受一個函數指針作爲參數,然後調用該函數有自己的論點:未通過指針常量數據作爲函數模板參數
typedef int (*my_func_ptr)(int);
int foo(my_func_ptr f) {
static int i = 0;
return i = f(i);
}
有時候,我需要通過函數foo
,它們不僅僅依賴整數輸入來輸出結果。
int add_strlen(int i, const char* s) {
return i + strlen(s);
}
我可以返工上面的代碼利用std::function
然後用std::bind
,但最好是對我來說,這些功能在編譯時創建的,所以我使用的模板。
template<const char* S>
int add_strlen(int i) {
return i + strlen(S);
}
/**
* Usage:
* char bar[] = "bar";
* foo(add_strlen<bar>);
*/
當使用指針作爲模板參數時,出現了我的問題。每當我使用指向任何類型的常量數據的指針作爲模板參數時,只要傳遞的參數被聲明爲該類型的非常量數組,它就只能編譯。
char char_array[] = "works";
const char const_char_array[] = "error";
char *char_ptr = "error";
const char *const_char_ptr = "error";
在Clang的相關錯誤(版本3.0-6)(於char_ptr
和const_char_ptr
錯誤是一樣的):
func_ptr.cpp:29:9: error: no matching function for call to 'foo'
foo(add_strlen<const_char_array>);
^~~
func_ptr.cpp:6:5: note: candidate function not viable: no overload of 'add_strlen' matching 'my_func_ptr' (aka 'int (*)(int)') for 1st argument
int foo(my_func_ptr f)
誰能給我解釋一下這是爲什麼?我看到它的方式,模板參數S
預計將是const char*
類型,在任何其他情況下,這意味着我可以傳入任何常量或非常量指針或類型爲char
的數組,並期望它可以工作。我希望能夠將我的數組聲明爲const
,因爲我甚至不想暗示它們是在運行時修改的。有沒有辦法讓我的數組const 和將它們用作模板參數?
編輯:感謝一些幫助(和Clang的更新版本,更好的錯誤)我能夠確定提供一個模板參數與內部鏈接是問題的一部分。通過將上述變量聲明爲extern,我可以毫無錯誤地使用add_strlen<const_char_array>
。我還創建了一個簡化的測試用例。它包括以下:
#include <cstring>
typedef int (*my_func_ptr)(int);
int foo(my_func_ptr f) {
static int i = 0;
return i = f(i);
}
template<const char* S>
int add_strlen(int i) {
return i + strlen(S);
}
extern char char_array[];
extern const char const_char_array[];
extern char *char_ptr;
extern const char *const_char_ptr;
char char_array[] = "foo";
const char const_char_array[] = "bar";
// assigning to string literal is deprecated
char *char_ptr = char_array;
const char *const_char_ptr = "baz";
int main(int argc, const char *argv[])
{
foo(add_strlen<char_array>); // works
foo(add_strlen<const_char_array>); // works
//foo(add_strlen<char_ptr>); // doesn't work
//foo(add_strlen<const_char_ptr>); // doesn't work
return 0;
}