私は2つの機能を持っています:
void foo(const char * p)
と
template<size_t T_Size>
void foo(const char (& p)[T_Size]) ;
呼び出しを考えると:
int main(int argc, char* argv[])
{
char a[21] ; // typeid : A21_c
sprintf(a, "a[21] : Hello World") ;
const char * b = "b : Hello World" ; // typeid : PKc
// note that literal "liter. : Hello World" has a typeid : A21_c
foo(a) ; // calls foo(const char (& p)[T_Size])
foo(b) ; // calls foo(const char * p)
foo("liter. : Hello World") ; // calls foo(const char * p) ???
return 0 ;
}
どうやら、foo
スタックベースの正しく宣言された配列での呼び出しは期待どおりに動作しますfoo
が、リテラル "liter. : Hello World" での呼び出しはそうではありません。
1 つのオーバーロードを他のオーバーロードよりも選択するために、シンボル ルックアップが従う規則は正確には何ですか?
宣言された配列と文字列リテラルの動作が異なるのはなぜですか?
ありがとう !
編集
目的の結果を得る (つまり、リテラル文字列をfoo(const char (& p)[T_Size])
関数に一致させる) 方法は、を削除してvoid foo(const char *p)
代わりに追加することです。
struct FooIndirect
{
const char * m_p ;
FooIndirect(const char *p) : m_p(p) {}
} ;
void foo(const FooIndirect & p)
{
// do something with p.m_p
}
この間接化により、テンプレート化された foo は文字列リテラルにより適したものになり、ユーザーは引き続きポインターを使用できます (間接化は最適化されたコンパイル モードで削除されます)。
g++ 4.4.3 でテストしましたが、すべてのコンパイラで同じように動作すると思います。