関数ポインターを引数として取り、その関数を独自の引数で呼び出す関数があります。
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 (ver. 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
は typeconst char*
であると予想されます。これは、他の状況では、任意の const または非 const ポインタまたは型の配列を渡して、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;
}