2010-02-01 7 views
13

누구나 함수 템플릿 오버로드에 대한 아이디어를 요약 할 수 있습니까? 중요한 것은 템플릿 매개 변수 또는 함수 매개 변수입니까? 반환 가치는 어떻습니까? 함수 템플릿함수 템플릿 오버로드

template<typename X, typename Y> void func(X x, Y y) {}; 

오버로드 된 함수 템플릿은 무엇 주어진 예를 들어

?

1) template<typename X> void func(X x, int y) {};  
2) template<typename X, typename Y> X func(X x, Y y) {};  
3) template<class X, class Y, class Z> void func(X x, Y y, Z z) {}; 
+13

모든 후행하는';'문자는 무의미합니다. 그것들은 요구되지 않으며 실제로 보는 것이 더 혼란스럽게 만듭니다. – Omnifarious

답변

21

두 번째 요소 만이 모호성을 유발합니다. 함수가 템플릿인지 여부에 관계없이 반환 유형에 따라 오버로드 할 수 없기 때문입니다.

당신이 사용할 수있는 다른 두 : 호출의 두 번째 인수를 int 인 경우

template<typename X> void func(X x, int y); 

은 세 가지로 FUNC를 호출하는 경우 예를 들어 func("string", 10);

template<class X, class Y, class Z> void func(X x, Y y, Z z); 

가 사용됩니다 사용됩니다 인수.


다른 답변에서 템플릿 함수 및 함수 오버로드가 섞이지 않는다고 언급하는 이유를 알 수 없습니다. 그들은 확실히하고, 호출 할 함수가 선택되는 특별한 규칙이 있습니다.

A function template can be overloaded with other function templates and with normal (non-template) functions. A normal function is not related to a function template (i.e., it is never considered to be a specialization), even if it has the same name and type as a potentially generated function template specialization.)

14.5.5 형판 비 (또는 "이하 템플릿"), 과부하 템플릿 바람직 예

template <class T> void foo(T); 
void foo(int); 

foo(10); //calls void foo(int) 
foo(10u); //calls void foo(T) with T = unsigned 

비 - 템플릿 파라미터 첫 과부하 또한이 규칙에 해당됩니다.

,보다 전문적인 일치가 선호하는 몇 가지 템플릿 사이

을 감안할 때 선택 : 당신은 표준의 같은 장에서 모든 규칙의 형식적인 설명을 찾을 수 있습니다

template <class T> void foo(T); 
template <class T> void foo(T*); 

int i; 
int* p; 
int arr[10]; 

foo(i); //calls first 
foo(p); //calls second 
foo(arr); //calls second: array decays to pointer 

(기능 템플릿)


마지막으로 두 개 이상의 과부하가 모호한 경우가 있습니다.

template <class T> void foo(T, int); 
template <class T> void foo(int, T); 

foo(1, 2); 

두 후보가 똑같이 특수화되어 있기 때문에이 호출은 모호합니다.

예를 들어 boost::disable_if을 사용하여 이러한 상황을 모호하게 할 수 있습니다. 예를 들어, 우리는 지정할 수 T = INT는 다음 두 번째 과부하 과부하 후보에 포함되지 않아야 할 때 : 여기

#include <boost/utility/enable_if.hpp> 
#include <boost/type_traits/is_same.hpp> 
template <class T> 
void foo(T x, int i); 

template <class T> 
typename boost::disable_if<boost::is_same<int, T> >::type 
foo(int i, T x); 

foo(1, 2); //calls the first 

라이브러리 제 과부하 리턴 유형에 "교체 실패"를 생성 , T = int 인 경우 과부하 후보 집합에서 제거합니다.

실제로 이런 상황이 발생하는 경우는 거의 없습니다.

+0

수정 해 주셔서 감사합니다! – Potatoswatter

+0

템플릿의 경우 void func (T); template void func (T *);'특별히 배열을 처리하는 버전을 만들 수도 있습니다 :'template void func ((T &)[N]);') 배열이 포인터로 쇠퇴하거나 호출하는 것을 방지합니다. 포인터 버전. –

+0

클래스 객체를 인스턴스화하기 위해' class_name :: class_name (const T &);와'template class_name :: class_name (const T *);'템플릿을 사용하려고합니다. char 배열 대신'class_name (const T *)'대신'class_name (const T &)'를 호출하려고합니다. include/Class_name.h | 67 | error : 'to_string (const 'class_name (const T &)'에서'class_name (const T *) '중에'to_string (T)'를 사용하고 있기 때문에 특별히 char 배열을 건네 둡니다. –

1

아래의 설명을 참조하십시오. 나는 원래의 게시물을 변경하지 않을 것입니다. 그러면 응답의 컨텍스트가 제거됩니다. 나는 그들의 입력 덧글 감사합니다, 그래서 친절에 관해서는 컴파일러가 그들을 볼지기 전에 # 정의를 확장 매크로 프리 프로세서처럼되고 템플릿을 고려


저를 아래로 투표 할 수 있습니다.

컴파일러는 템플릿 매개 변수를 "확장"한 다음 함수 선언을 봅니다. 그래서, 템플릿 매개 변수 == 함수 매개 변수. 동일한 함수를 두 번 선언하면 오류가 발생합니다.

반환 유형에 대해 문의하십시오. 그것은 함수의 '서명'의 일부입니다. 동일한 매개 변수이지만 다른 리턴 유형을 갖는 두 개의 함수는 두 가지 다른 함수입니다.

+4

비 템플릿 함수의 반환 유형은 서명의 일부가 아닙니다 (http://stackoverflow.com/questions/290038/is-the-return-type-part-of-the-function-signature/290048#290048 참조).). –

+1

전 처리기 매크로와의 비교에는 다소 결함이 있습니다. 과부하에 대한 특별 규칙이 있습니다. 'foo (int);'템플릿'foo (int);'템플릿'foo (int);'템플릿을 가지고 있다면'foo (3);'와 같은 호출은 분명히 후자로 변환 될 것입니다. 정확하게). – UncleBens

+0

반환 유형이 retrun 유형에서 오버로드 할 수있는 서명의 일부인 경우 –

3

함수 템플릿과 함수 오버로딩이라는 두 가지 별도의 기능이 있습니다. 두 개의 별개의 템플릿 선언은 서로간에 과부하가 될 수 있으므로 명시된 바와 같이 질문이 이해가되지 않습니다. (세 가지 "오버로드"는 첫 번째 템플릿을 기반으로하지 않으며 동일한 함수 이름에 네 가지 오버로드가 있습니다.) 실제 오버로드는 이고 콜은입니다. 원하는 오버로드를 호출하는 방법은 무엇입니까?

먼저 반환 형식은 관련된 템플릿이 있는지 여부에 관계없이 오버로드 프로세스에 참여하지 않습니다. 그래서 # 2는 # 1과 잘 어울리지 않을 것입니다.

두 번째로, 함수 템플리트 오버로드 해석에 대한 규칙은보다 일반적으로 사용되는 클래스 템플리트 전문화 규칙과 다릅니다. 둘 다 본질적으로 같은 문제를 해결하지만,

  • 클래스 템플릿에 대한 규칙 예를 재귀 허용, 간단하고 강력한, 함수 템플릿에 대한 반환 형식 만
  • 규칙을 다른 (회원) 기능은 허용 컴파일러는 함수 인수 유형에서 템플릿 인수를 파악하는

당신은 함수 템플릿 오버로드를 사용하여 특정 문제를 해결할 수 있습니다,하지만 당신은 문제가 규칙이 더 이상 적은 사람들이 같이 발생하는 모든 버그 수정이있을 수 있습니다 그들의 복잡한 것에 익숙하다. 몇 해 동안의 템플릿 해킹으로 미묘한 함수 템플릿 오버로딩이 가능하다는 것을 알지 못했습니다. 부스트 (Boost) 나 GCC의 STL과 같은 라이브러리에서는 대체 접근법이 보편적이다. 템플릿 랩퍼 클래스를 사용하십시오.

template< typename X, typename Y > 
struct functor { 
    void operator()(X x, Y y); 
}; 
template< typename X > // partial specialization: 
struct functor< X, int > { // alternative to overloading for classes 
    void operator()(X x, int y); 
}; 

이제 꺽쇠 괄호없이 암시 적 인스턴스화 구문을 희생합니다.당신이 다시 얻고 싶은 경우에, 당신은 ... 나는 그 클래스 [부분] 전문화 할 수없는 함수 오버로딩 (공제 외에) 아무것도 할 수 있는지 여부를 듣고 싶네 다른 함수를

template< typename X, typename Y > void func(X x, Y y) { 
    return functor< X, Y >()(x, y); 
} 

필요

그리고 과부하 # 3은 다른 과부하보다 다른 인수 번호를 가지므로 모호성이 발생하지 않습니다.

+0

부분 전문화 작업에 대한 +1 –

+0

예제가 모호하지 않은 것 같습니다. 이 호출은 두 번째 매개 변수와 일치합니다 (하나의 매개 변수는 int와 정확하게 일치합니다). 아마도 다음과 같은 오버로드를 의미했을 것입니다 : template void func (int x, X y); template void func (X x, int y);' – UncleBens

+0

두 번째'func'은 첫번째'func'에 의해 받아 들여지는 인수의 일부를 거부하지만 다른 방법은 허용하지 않습니다. 일반 함수 호출의 경우,이 순서를 무시하면 호출은 모호합니다. 왜냐하면 템플릿 매개 변수가 마찬가지로 'int'로 추론되기 때문입니다. –