2017-01-03 18 views
7
#include <iostream> 
using namespace std; 

void f(const char* arg) 
{ 
    cout << "arg is a pointer" << endl; 
} 

template<size_t N> 
void f(const char (&arg)[N]) 
{ 
    cout << "arg is an array." << endl; 
} 

int main() 
{ 
    f(""); 
} 

マイコンパイラは3.8です。なぜclangは文字列リテラルを配列ではなくポインタとして扱うのですか?

出力である:

argがしかし、cppreference.com

に従って文字接頭辞文字列のタイプは、CONSTチャーポインタ

になっています[] 。

なぜ、オーバーロードの解像度が期待どおりに動作しないのですか?

+2

相当する例ですが、テンプレートを抽象化しています。http://melpon.org/wandbox/permlink/0nGenu5Ysj40wS8u –

+0

[関連する](https://stackoverflow.com/questions/16708307/is-it-possible-to) -legally-overload-a-string-literal-and-const-char)、可能なdupeです。どう思いますか? –

答えて

8

期待どおりに振る舞うんが、あなたは自分の期待;-)

const char[1]const char (&)[1]があり、異なる種類を調整する必要があります。

const char*(配列からポインタへの変換)とconst (&char)[1](同一性変換)への変換はどちらも完全一致とみなされますが、非テンプレートはテンプレートよりも一致します。

あなたは、非テンプレートサイズ固有の過負荷を書く

void f(const char (&arg)[1]) 

場合は、関数呼び出しがあいまいであるというエラーが発生します。

+2

遅すぎます。 :(参考のために、関連標準はN4141の表12にある –

1

@ molbdniloの回答が正しいです。 1つの詳細を追加するには:直感は正しいでしょうし、コンパイラはテンプレートを呼び出すことによって配列からポインタへの変換を避けることを好みます。しかし、lvalueの変換(左辺値、配列対ポインタ、関数対ポインタ)は、オーバーロードランク付けでは特に無視されています(over.ics.rank)§13.3.3.2/ 3.2.1。

workaroundがあります。オーバーロードの優先順位のバランスを復元するために、偽のvolatileを追加してください。パラメータを使用する前に必ずconst_castで削除してください。

関連する問題