2017-01-03 13 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), 가능한 속도. 어떻게 생각해? –

답변

8

예상대로 작동 않습니다, 당신은 당신의 기대 ;-)

const char[1]const char (&)[1]는 다른 유형을 조정해야합니다.

const char* (배열 대 포인터 변환) 및 const (&char)[1] (ID 변환)으로의 변환은 모두 정확히 일치하는 것으로 간주되지만 비 템플릿이 템플릿보다 더 적합합니다. 함수 호출이 모호 당신이 오류가 발생합니다

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

가 아닌 템플릿 사이즈 별 과부하를 작성하는 경우

.

+2

너무 느립니다. :(관련 표준 규격은 N4141의 표 12에있다. –

1

@ molbdnilo 님의 답변이 맞습니다. 하나의 세부 사항을 추가하려면 : 직감이 정확하고 컴파일러는 템플릿을 호출하여 배열 대 포인터 변환을 피하는 것이 좋습니다. 그러나 lvalue 변환 (lvalue-to-rvalue, 배열 대 포인터 및 함수 대 포인터)은 오버로드 순위에서 특히 무시됩니다 (over.ics.rank) §13.3.3.2/3.2.1.

workaround가 : volatile 가짜를 추가하여 과부하 우선 설정의 균형을 복원하십시오. 매개 변수를 사용하기 전에 const_cast으로 제거하십시오.