2009-05-08 6 views
1

나는 컴파일러 오류를 해결하는 방법을 알아내는 데 어려움을 겪고 있습니다. 나는이 간단한 경우의 표현으로 그것을 아래로 감소했습니다어떻게이 템플릿 코드를 모호하게 할 수 있습니까?

enum EAtomId { EAtomId_Test }; 

int StringFormat(char* o_dest, size_t i_destSizeChars, const char* i_format, ...); 

template <size_t SIZE> 
int StringFormat(char (&o_dest)[SIZE], EAtomId i_format, ...); 

void func() 
{ 
    char textBuffer[1000]; 
    StringFormat(textBuffer, EAtomId_Test, "hi there"); 
} 

컴파일러 오류는 다음과 같습니다 BTW 전체 오류의

repro.cpp(17) : error C2666: 'StringFormat' : 2 overloads have similar conversions 
    C:\Users\sbilas\Desktop\repro.cpp(9): could be 'int StringFormat(char *,size_t,const char *,...)' 
    while trying to match the argument list '(char [1000], EAtomId, const char [9])' 

합니다. 나는 조금 두 가지 사용 가능한 버전을 나열하지 않습니다 놀랍군요.

나는이 오류와 몇 가지 문제가 있습니다. 첫째, 모호한 이유는 모르겠다. 일치하는 명백한 경우 컴파일러는 char (&) [] 버전을 보지 않아야합니까? 둘째, 조회를 수행 할 때 해당 열거 형을 size_t로 변환하지 못하게하려면 어떻게해야합니까? 매우 구체적인 C++ 규칙을 실행하고있는 것처럼 보입니다.

나에게 가장 쉬운 해결 방법은 실제 버퍼 앞에 버퍼 크기의 size_t를 넣는 것입니다. 그러나 그것은 우리가 코드에 버퍼를 넣고 크기를 넣는 우리의 모든 관습을 깨뜨릴 것입니다. 이것을 할 또 다른 방법이 있습니까?

이것은 VC++ 2005 btw에 있지만 다른 크로스 컴파일러에서 재생합니다 (이것은 크로스 플랫폼 게임에 있습니다).

int StringFormat(char* o_dest, size_t i_destSizeChars, 
       const char* i_format, ...); 

template <size_t SIZE> 
int StringFormat(char (&o_dest)[SIZE], EAtomId i_format, ...); 

기능 템플릿 및 일반 (비 템플릿) 기능을 모두 사용할 수있는 경우 인수 종속 조회 및 대체 규칙에 최대 읽기 :

답변

2

위 코드의 문제는 일반적인 과부하 해결 규칙에 의한 것이며 템플릿과 관련이 없습니다. 세트를 운동을

  • 인수의 각 세트의 경우 : 오버로드 확인 작업

    enum EAtomId { EAtomId_Test }; 
    const int SIZE=1000; 
    
    int StringFormat(char * s 
        , size_t i_destSizeChars 
        , const char* i_format 
        , ...); 
    
    int StringFormat(char (&a)[SIZE] 
        , EAtomId i_format 
        , ...); 
    
    void func() 
    { 
        char textBuffer[SIZE]; 
        StringFormat (textBuffer, EAtomId_Test, "hi there"); 
    } 
    

    적용 가능한 규칙을 다음과 같이 (13.3.3) : 여전히 두 가지 일반적인 기능을 가진 다음 코드는 모호성을 보여줍니다 발생하는 전환 수

  • 최상의 기능은 모든 전환이 다른 모든 과부하의 전환보다 적게 좋은 기능입니다.

    기능 : 1 :

    1. textBuffer-> S : 포인터 배열 (정확한 13.3.3.1 일치를 우리가 차례대로 각 촬영

.1/3) - 신원

  • EAtomId_Test-> i_destSizeChars :
  • 문자열 literal-> const를 문자 * 가능한 홍보 및 적분 변환 : 배열이 포인터에
  • 기능 2 :

    1. textBuffer-> a : ID 변환
    2. EAtomId_Test-> EAtomId : Identity 변환
    3. 문자열 리터럴 -> 엘 lipsis : 줄임표 변환 차례로 이러한 변환을 각각 비교

    당신은이 :

    1. 기능 1 기능 2
    2. 기능이 기능보다 1
    3. 기능 1 기능보다 더와 동일 2

    따라서 기능 1도 기능 2도 최소한 모두에 적합하지 않습니다. 변환 때문에 호출이 모호합니다.

    +0

    자세한 답변을 보내 주셔서 감사합니다. 내가 당신을 올바르게 이해한다면, param 2에서 "가능한 승진과 통합 전환"은 "신원 전환"만큼이나 강력합니까? 나는 컴파일러가 변환을 필요로하는 경우보다 identity를 선택하기를 원할 것이다. 순서를 변경하는 것 외에이 문제를 해결할 방법을 제안 할 수 있습니까? 내가 뭘하려고 정적 크기의 문자열 버퍼에 대한 자동 길이 안전을 얻을 수 있습니다. 동시에 형식 문자열을 지정하는 두 가지 방법이 있습니다. 리터럴 및 "원자"를 통해 (현지화를 위해 사전에서 찾아 보았습니다). – scobi

    2

    당신은 StringFormat 두 선언이있다.

    +0

    위의 두 가지 사항 중 어느 것도 적용되지 않습니다. 검색 집합에만 추가되므로 ADL은 실제로 여기에 적용되지 않지만이 두 함수는 "일반 조회"에 표시됩니다. 함수 템플릿 및 비 템플릿 함수의 모호성은 두 함수 유형이 동일한 경우에만 적용됩니다. (13.3.3/1). –

    +0

    @Richard Corden : 과부하 해결을 의도했습니다. 이것들은 점으로서의 것이 아니라 오히려 완결을위한 것입니다. 나는 그들을 잘못 주문했다 - 내가 마지막으로 말한 것을 넣어 놓고 ADL에 대한 요점을 추가해야했다. – dirkgently

    관련 문제