2012-08-28 2 views
2

템플릿 함수의 반환 형식이 첫 번째 인수 (T)의 반환 형식과 동일하기 때문에이 사실을 알고 있습니다.
이 템플릿을 수정하여 모든 경우에 올바르게 작동하도록하려면 어떻게해야합니까?일반적인 max 함수를 구현하는 방법은 무엇입니까?

#include <iostream> 
using namespace std; 
template <typename T, typename U> 
T max(T x, U y) 
{ 
    return x>y ? x : y; 
} 

int main() 
{ 
    cout<<max(17.9,17)<<"\n"; 
    cout<<max(17,17.9)<<"\n"; 
} 

출력 :

17.9 
17 
+0

'double' 또는'int'에 암시 적으로 캐스트하기 때문에 잘못되었습니다. 표준 유형에 대한 특수 버전을 작성할 수 있습니다. –

+0

std :: max의 문제점은 무엇입니까? – Moritz

+1

@ 모리츠, 질문은 최대 2 개의 숫자를 찾는 방법에 관한 것이 아닙니다. – cppcoder

답변

3

출력은 정확하다. 유형을 지정하지 않았으므로 사용하려는 유형을 사용하지 않는다고 불평하는 것은 합리적이지 않습니다. 특정 유형을 원할 경우 매개 변수가 모두인지 확인해야합니다.

첫 번째 매개 변수는 double으로 캐스팅 할 수 있습니다. 또는 구체적으로
max<double, double>을 호출 할 수 있습니다. 당신이 정말로 원한다면 max<int, double> 및 유사한 조합을 전문화 할 수도 있습니다.

+0

Scwartz,이 경우 템플릿 ''만 유용합니까? 다른 모든 조합은 특수화되어야합니다. – cppcoder

+0

@cppcoder가 반드시 필요한 것은 아닙니다. 서로 다른 두 가지 입력 유형에 대해 반환 할 내용을 결정하면됩니다. 그런 다음'auto'와 후행 반환 형식 또는'std :: result_of'를 사용하여 구현할 수 있습니다. – juanchopanza

+0

이 옵션을 사용했습니다 :'Cout < (17,17.9) << "\ n"; ' – cppcoder

8

구현에 대한 동작은 정확하지만 출력을 원하지 않을 수 있습니다. 코드에서 반환 유형의 문제입니다.

당신은 당신이 C++ (11)를 사용할 수 있는지 trailing-return type을 사용할 수 있습니다 :이 출력 줄 것

template <typename T, typename U> 
auto max(T x, U y) -> decltype(x>y ? x : y) //C++11 only 
{ 
    return x>y ? x : y; 
} 

:

17.9 
17.9 

내가 그 원하는 출력 바랍니다.

온라인 데모 : http://ideone.com/2Sh5Y

1

당신이 (auto 늦게 반환 형식 및 decltype와) 타입 추론을 사용할 수 있습니다 (11) C++에서이 :

template <typename T, typename U> 
auto max(T x, U y) -> decltype(x>y ? x : y) 
{ 
    return x>y ? x : y; 
} 
2

이 C++ 03에 대한 답변입니다. C++ 11의 경우 auto/decltype을 사용하십시오 (다른 답변 참조). template CommonNumericType<T1,T2> :

template <typename L, typename R> 
typename CommonNumericType<T1,T2>::Type max(L x, R y) 
{ 
    return x>y ? x : y; 
} 

그리고 숫자 유형의 모든 가능한 쌍에 대해이 CommonNumericType 전문 :

당신은 다른 템플릿을 만들어야합니다

template <typename L, typename R> 
struct CommonNumericType; 
template <typename T> 
struct CommonNumericType<T,T> { 
    typedef T Type; 
}; 
template <typename L> 
struct CommonNumericType<L,long double> { 
    typedef long double Type; 
}; 
template <typename R> 
struct CommonNumericType<long double,R> { 
    typedef long double Type; 
}; 
// ... 
template <> 
struct CommonNumericType<int,short> { 
    typedef int Type; 
}; 
// and many others stuff 

내가 몇 가지 숫자 유형 계층을 생각할 수 - 플로트 int 타입 이전의 타입 - 등등.

template <typename T> 
struct NumericTypeOrder; 
template <> 
struct NumericTypeOrder<long double> { enum { VALUE = 1 }; }; 
template <> 
struct NumericTypeOrder<double> { enum { VALUE = 2 }; }; 
template <> 
struct NumericTypeOrder<float> { enum { VALUE = 3 }; }; 
template <> 
struct NumericTypeOrder<unsigned long long> { enum { VALUE = 4 }; }; 
// etc for all numeric types - where signed char is last one... 

template <typename L, typename R, bool L_bigger_than_R> 
struct CommonNumericTypeImpl; 
template <typename L, typename R> 
struct CommonNumericTypeImpl<L,R,true> { 
    typedef L type; 
}; 
template <typename L, typename R> 
struct CommonNumericTypeImpl<L,R,false> { 
    typedef R type; 
}; 
template <typename L, typename R> 
struct CommonNumericType 
: CommonNumericTypeImpl<L,R,NumericTypeOrder<L>::value >= NumericTypeOrder<R>::value > { 
}; 

하거나 매크로를 사용하여 : : <number of numeric types>^2 꽤 큰 숫자 때문에

#define max(l,r) ((l) >= (r) ? (l) : (r)) 

훨씬 간단을, 그렇지?C와

+0

+1 for the C++ 03 effort. 매크로에 관해서는 매크로의 모든 문제점을 가지고 있으며, 특히 인수의 * one *을 두 번 평가한다는 사실이 있습니다. 'max' (f(), g())':'f'를 평가 한 다음'g'를 평가 한 다음 다시 최대를 산출 한 것을 고려하십시오. 조작의 비용 외에도, 기능이 다중으로 평가된다는 사실은 부작용이있는 경우에는 손상 될 것입니다. –

+0

타입리스트가'CommonNumericType'을 좀 더 우아하게 구현하는 데 도움이 될 것이라고 내 직감은 말합니다. – Nawaz

+0

@David - 당신은 매크로에 관한 것입니다. 그러나 매크로를 사용하면 더 큰 변수에 값을 할당 할 수 있습니다. 'max (a, b) = 7' 여기서 a, b는 변수입니다. 템플릿으로 할당 할 수있는'max (...)'를 얻는 방법에 대한 기사를 기억합니다. 그러나 지금은 찾을 수 없습니다. – PiotrNycz

3

++ (11) 쉬운, 사용 표준 : common_type <> 특성 :

template <typename T, typename U> 
typename std::common_type<T,U>::type max(T x, U y) /// why not const& T and const& U ? 
{ 
    return x>y ? x : y; 
} 

common_type <>는 C++ 11

이후 새로운 모두 decltype 키워드와 declval <> 특성을 사용하여
+0

+1 Re. 코멘트 : 프리미티브 타입의 경우 참조를 전달하고 싶지 않습니다. 비용이 실제로 값을 복사하는 것보다 클 수 있습니다. 즉, 사용자가'std :: string'처럼 복잡한 유형을 전달하는 것을 차단하는 것은 없습니다. –

+0

'declval'은 * 키워드 *가 아닙니다. 함수 템플릿입니다. 'decltype'은 C++ 11의 키워드입니다. – Nawaz

+0

@Nawaz 님이 그것을 고쳤습니다. – marcinj

관련 문제