2012-05-16 3 views
2

오늘 업무가 시작되어 커뮤니티에 버릴 것이라고 생각했습니다.내 기능에 대한 일반적인 산술 변환 수행?

는 동료는 다음 코드 (다소) 작성 :

#include <algorithm> 

double chop(double x) { 
    return std::max(0, x); 
} 

을하지만 std::max 정확한 유형이 같을 인수 모두를 원하기 때문에이 경우에도, 컴파일되지 않습니다. 나는 이것이 참조 쌍을 취할 수 있고 참조를 리턴 할 수 있다고 믿는다. 이것은 사용자가 정의한 유형에서 호출 할 때 원하는 것 같다. 공정하다.

물론 픽스는 std::max(0.0, x)입니다.

이제 거짓말을 했으니 잠시 나와 함께있어주십시오. 저의 동료가 실제로 쓴 것은 :

// Included from a very old header file written by someone long gone 
template<class T1, class T2> 
inline T1 myMax(T1 x, T2 y) { 
    return (x < y) ? y : x; 
} 

double chop(double x) { 
    return myMax(0, x); 
} 

이 컴파일됩니다! 그러나 x가 0.25와 같으면 놀랄만 한 결과를 산출합니다. 나는 그에게 문제를 찾기까지 얼마나 걸렸는 지 잘 모르겠다. 그리고 그것을 찾은 후에도, 왜 그것이 작동하지 않는지를 물어야했다.

내 대답은 (버그를 수정하는) 0 대신 0.0을 사용하고, myMax (생각할 때 매우 놀랄 정도의 행동) 대신 std::max을 사용합니다.

그러나 그는 왜 그런지 궁금합니다. 내 말은, 그는 0 + x 또는 0 * x 또는 0 - x이라고 쓸 수 있습니다. 그렇다면 왜 myMax(0, x)이 될까요? 내가 통과하고 정수형의 모든 쌍에 대한 WiderType에 대한 전문성을 추가, 플러스 일부는 다른 일반적인 산술 연산을 수행 할 수

// this is from the .hh file 

// template meta-program to compute the "wider" of two types given as argument 
template<class T1, class T2> 
struct WiderType { 
}; 

// Partial specialization for case where both types are same 
template<class T> 
struct WiderType<T, T> { 
    typedef T type; 
}; 

// Specialization for first type "int" and second type "double" 
template<> 
struct WiderType<int, double> { 
    typedef double type; 
}; 

template<class T1, class T2> 
inline typename WiderType<T1,T2>::type 
myMax(T1 a, T2 b) { 
    return ((a < b) ? b : a); 
} 


// this is from the .cc file 

double chop(double x) { 
    return myMax(0, x); 
} 

// just to show this still works 
int chop(int x) { 
    return myMax(0, x); 
} 

을 지금 : 여기

은 자신이 원하는 것을 그에게주는 나의 첫 번째 패스입니다 전환 수. (그리고 나는 그것을 UsualConversions 또는 somesuch로 이름을 바꿀 수 있다고 생각합니다.)

더 쉬운 방법이 있습니까? 즉, C++ 언어는 다양한 기본 제공 산술 연산자와 같은 인수를 사용하여 동일한 변환을 수행하는 자체 함수를 정의하는 간단한 방법을 제공합니까?

답변

7

, 당신은뿐만 아니라이 작업을 수행 할 수 있습니다

template<typename T1, typename T2> 
typename std::common_type<T1, T2>::type max(T1&& a, T2&& b) { 
    return a < b ? b : a; 
} 

common_type는 형식 정의가 마치 있도록 두 가지 유형이 암시 적으로 변환 할 수있는 유형이 그 안에 type을 가지고, 예를 들어 doubleint이면 double을 반환하지만 intint 인 경우 int을 반환합니다.

template<typename T1, typename T2, typename T3> 
void max(const T1& a, const T2& b, T3& dst) { 
    dst = a < b ? b : a; 
} 

double d; 
max(0, 43.12, d); 

그것은 데 꽤 서투른처럼 사용 :

전혀 C++ (11)를 사용할 수없는 경우는, 다음 내가 생각할 수있는 유일한 것은 이것이다 그래도 변수를 선언 할 수 있습니다. 당신이 예뻐 생각하면, 당신은 또한이 작업을 수행 할 수 있습니다

template<typename RetType, typename T1, typename T2> 
RetType max(const T1& a, const T2& b) { 
    return a < b ? b : a; 
} 

다음

return max<double>(0, 43.11); 
+0

이것은 내 대답보다 낫다. 그것은 더 명백하고 속임수에 의지하지 않습니다. –

+0

이 질문에 Niceness 레벨이 너무 높습니다. – ScarletAmaranth

+0

반환 유형에'typename'이 없습니다. – ildjarn

4

나는 C++ 11 이전에 좋은 방법을 모르지만 이제 이와 같은 것을 할 수 있습니다.

template<class T, class U> 
auto myMax(T&& t, U&& u) -> decltype(t + u) 
{ 
    return t < u ? u : t; 
} 

decltype(t + u)TU의 일반적인 유형은 산술 식에있을 것입니다 무엇을 작동하고 있음을 사용하는 템플릿에 대한 반환 형식으로. 찰스 베일리의 대답에 추가

+0

아주 좋은 좋은 선생님. – ScarletAmaranth

관련 문제