6

Sun Studio 12.1 및 새로운 컴파일러 [CC : Sun C++ 5.10 SunOS_sparc 2009/06/03]로 마이그레이션 중입니다. 이전 버전의 Sun Compiler [CC : Sun WorkShop 6 update 2 C++ 5.3 2001/05/15]에서 컴파일 한 코드를 컴파일하는 동안 컴파일 오류가 발생합니다.Sun Studio 12에서 템플릿 컴파일 오류가 발생했습니다.

이것은 컴파일 오류입니다.

"Sample.cc": Error: Could not find a match for LoopThrough(int[2]) needed in main(). 1 Error(s) detected. *** Error code 1.

코드 : 나는 일반 버전의 코드를 주석 처리를 제거하면

#include <iostream> 

#define PRINT_TRACE(STR) \ 
std::cout << __FILE__ << ":" << __LINE__ << ":" << STR << "\n"; 

template<size_t SZ> 
void LoopThrough(const int(&Item)[SZ]) 
{ 
    PRINT_TRACE("Specialized version"); 
    for (size_t index = 0; index < SZ; ++index) 
    { 
     std::cout << Item[index] << "\n"; 
    } 
} 


/*  
    template<typename Type, size_t SZ> 
    void LoopThrough(const Type(&Item)[SZ]) 
    { 
     PRINT_TRACE("Generic version");   
    } 
*/ 



int main() 
{ 
    { 
     int arr[] = { 1, 2 }; 
     LoopThrough(arr);  
    } 
} 

, 코드가 잘 컴파일 및 일반 버전이라고합니다. 익스텐션이 비활성화 된 MSVC 2010 및 ideone here과 같은 경우에는이 문제가 발생하지 않습니다. 특수 버전의 함수가 호출됩니다. 이제 질문은 Sun Compiler의 버그입니까?

예인 경우 어떻게하면 버그 보고서를 제출할 수 있습니까?

+1

어쩌면 const를 제거합니까 :

가장 좋은 임시 수정은 아마 두 번째 오버로드인가? – PlasmaHH

+0

예. const를 제거하거나 int arr []에 const를 추가하면 해결할 수 있습니다. 그러나 이것이 컴파일러의 버그인지 아니면 내 이해가 잘못된 것인지 알고 싶습니다. – Jagannath

+2

clang, gcc, comau 및 msvc의 최신 버전이 동의하면 가능성이 있으며, SunCC의 버그입니다. SunCC는 버그가있는 것으로 유명합니다. 그래서 gcc를 사용하지 않는 이유는 무엇입니까? – PlasmaHH

답변

2

컴파일러에

출력이 경우 표준을 다음과 버그가되지 않습니다. 관련 섹션을 살펴 보겠습니다. 13.3/3에서

먼저 우리는이 :

...

— First, a subset of the candidate functions—those that have the proper number of arguments and meet certain other conditions—is selected to form a set of viable functions (13.3.2).

— Then the best viable function is selected based on the implicit conversion sequences (13.3.3.1) needed to match each argument to the corresponding parameter of each viable function.

그래서 두 함수는 인수의 같은 수의 후보자로 간주됩니다. 이제 우리는

13.3.3에서 최고의 가능한 기능을 찾을 수있다 :

let ICSi(F) denote the implicit conversion sequence that converts the ith argument in the list to the type of the ith parameter of viable function F. 13.3.3.1 defines the implicit conversion sequences and 13.3.3.2 defines what it means for one implicit conversion sequence to be a better conversion sequence or worse conversion sequence than another

을 다음 우리는 두 가지 기능 (CONST 추가) 첫 번째 규칙에 대한 동일

Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then

— for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2), or, if not that,

— F1 is a nontemplate function and F2 is a template function specialization, or, if not that,

— F1 and F2 are template functions, and the function template for F1 is more specialized than the template for F2 according to the partial ordering rules described in 14.5.5.2, or, if not that,

을 가지고, 두 번째 규칙은 적용되지 않습니다 (둘 다 템플릿 임). 그래서 우리는 세 번째 규칙으로 이동합니다. 14.5.5.2 (필자의 요청에 따라 인용)에서 우리는 const Item 버전보다 const int 버전의 함수가 더 전문화되어 있으므로 가장 적합한 일치 항목은 const int 오버로드이며 호출해야합니다.workarodun이

template<size_t SZ> 
void LoopThrough(int (&Item)[SZ]) 
{ 
    LoopThrough(static_cast<const int (&)[SZ]>(Item)); 
} 
1

컴파일러가 버그입니다. 두 가지 오버로드는 템플릿 인수가 추론되며 오버로드 해상도는 가장 특수한 것을 선택해야합니다. 그래서 새로운 컴파일러를 얻는 것 외에 무엇을 할 수 있습니까?

첫 번째로, 컴파일러를 준수하는 경우에도 다른 기능 템플릿 오버로드를 갖는 것이 일반적으로 바람직하지 않다는 것을 깨닫는 것이 도움이됩니다. 예 : Herb Sutter 및 Andrei Alexandrescu의 C++ Coding Standards: 101 Rules, Guidelines, and Best Practices 항목 66

다행히도이 항목은 가능한 수정을 제안합니다. 단일 함수 템플리트를 정의하고 해당 함수 템플리트가 클래스 템플리트 함수 오브젝트에 작업을 위임하도록 만하면됩니다. 그런 다음 ints에 대해이 클래스 템플릿을 부분적으로 특수화 할 수 있습니다.

#include <iostream> 

#define PRINT_TRACE(STR) \ 
std::cout << __FILE__ << ":" << __LINE__ << ":" << STR << "\n"; 

namespace detail {  

// primary template 
template<typename Type, size_t SZ> 
class LoopThroughHelper 
{ 
public: 
    void operator()(const Type(&Item)[SZ]) 
    { 
     PRINT_TRACE("Generic version");   
    } 
}; 

// partial specialization for int arrays 
template<size_t SZ> 
class LoopThroughHelper<int, SZ> 
{ 
public: 
    void operator()(const int(&Item)[SZ]) 
    { 
     PRINT_TRACE("Specialized version"); 
     for (size_t index = 0; index < SZ; ++index) 
     { 
      std::cout << Item[index] << "\n"; 
     } 
    } 
}; 

} // namespace detail 

// one function template to rule them all 
template<typename Type, size_t SZ> 
void LoopThrough(const Type(&Item)[SZ]) 
{ 
    detail::LoopThroughHelper<Type, SZ>()(Item);   
} 

int main() 
{ 
    { 
     int arr[] = { 1, 2 }; 
     LoopThrough(arr);  
    } 
} 

대부분의 경우 컴파일러는 함수 개체에 대한 호출을 인라인하고 임시를 완전히 최적화합니다. 다행히도 컴파일러가 클래스 템플릿의 부분적 특수화를 올바르게 구현했기를 바랍니다. Ideone

+0

OP 문제는 컴파일러가 const가 아닌 배열을 const 배열 매개 변수에 바인딩하지 않기 때문에 하나의 템플릿에서만 컴파일에 실패한다는 것입니다. –

+0

@ MarkB 여러 함수 오버로드 대신 특수 함수 객체를 추가로 간접적으로 처리하는 것은 좋은 스타일입니다. – TemplateRex