0

반올림 값을 반환하기 전에 반올림해야하는 유형을 정의하는 추가 템플릿 인수로 간단한 라운드 템플릿 함수를 만들었습니다.오버로드로 부분 템플릿 전문화

template <typename T, typename U> 
T round(U val) { 
    T result; 
    if (val >= 0) 
     result = (T)(floor(val + (U)(.5))); 
    else 
     result = (T)(ceil(val - (U)(.5))); 
    return result; 
} 

int a = round<int>(5.5); // = 6 
// no compiler warnings 

하지만 추가 템플릿 인수를 남겨 두어 이미 인수로 추가 한 유형을 삽입하지 않아도됩니다.

template <typename T> 
T round(T val) { 
    return round<T>(val); 
} 

double b = round(5.5) // = 6.0 
// C2668 

그러나, 이제 컴파일러는 불평 :

오류 C2668을 : 내가 생각

오버로드 된 함수에 대한 모호한 전화를 항상을해야하는 가장 구체적인 템플릿을 선택할 것 컴파일러 마지막 것. 왜 이것이 사실이 아니며 해결 방법이 있습니까 (특히이 라운드 기능에는 해당되지 않음)?


애매한 호출 round(5.5)를 가리키는 것이 아니라에 return round<T>(val);되지 않았습니다. 이 질문에 대한 답변은 오버로드 된 함수의 반환 값을

return round<T,T>(val); 

으로 다시 작성하여 문제를 해결하는 것입니다.

the answer-my other question에 대해 galop1n에게 감사드립니다.

+0

마지막 하나는 다른 것보다 구체적이지 않습니다. – user3286380

+0

'라운드'는 자신이 생각하는 것과 다릅니다 (예 : ['a'는 5와 같습니다] (http://coliru.stacked-crooked.com/a/4ab101714d2ef8ba)). – TemplateRex

+0

@TemplateRex : 예 오타를 만들었습니다. 지금 수정되었습니다 – Didii

답변

2

템플릿 인수 공제 중 반환 유형이 추론되지 않으므로 오류가 발생합니다. 대신 연역 함수 인수로 대체됩니다. 두 오버로드에는 동일한 인수가 있기 때문에 컴파일러 오류를주는 과부하 resoution은 모호합니다.

C++ 11에서는 함수 템플릿에 대한 기본 템플릿 매개 변수를 정의 할 수 있습니다. 기본 반환 값과 같은 별도의 기본 함수 매개 변수를 추가하면 명시 적으로 기본 반환 값 성공하지 않는 한, 당신은 항상, 반환 형식으로 인수 유형을 얻을 것이다 :

#include <iostream> 
#include <cmath> 
#include <type_traits> 

template <typename T, typename Ret = T> 
Ret xround(T val, Ret ret = Ret()) { 
    return static_cast<Ret>(
     (val >= 0) ? 
     floor(val + (T)(.5)) : 
     ceil(val - (T)(.5)) 
    ); 
} 

int main() 
{ 
    auto a = xround(5.5, int()); // = 6 
    static_assert(std::is_same<decltype(a), int>::value, ""); 
    std::cout << a << "\n";  

    auto b = xround(5.5); // = 6.0 
    static_assert(std::is_same<decltype(b), double>::value, ""); 
    std::cout << b << "\n"; 
} 

Live Example

참고하는 I if-else 대신에 삼항 연산자를 사용했고, xround으로 함수의 이름을 바꿨다. C++ 11에서는 round이 이미 <cmath> (여기에는 물론 사용할 수도 있음)이기 때문에.

참고 : 임시는 태그 디스 패칭과 유사합니다. 반환 유형을 결정하는 데 전적으로 사용되며 실제 임시는 컴파일러에 의해 최적화되어야합니다.

+0

늦게 답변 해 주셔서 감사합니다. 문제는 외관상으로는 Visual Studio 2012에서 기본 템플릿 인수가 지원되지 않는다는 것입니다. 따라서 귀하의 대답이 맞으면 내 문제가 해결되지 않습니다. – Didii

+0

@Didii Visual Studio 2012 November CTP 또는 Visual Studio 2013로 업그레이드 할 수있는 경우 기본 함수 템플릿 인수가 지원됩니다. – TemplateRex

0

문제는 템플릿 전문 분야가 아니라 과부하입니다.

이 비슷하다

template <typename T, typename U = T> 
T fn(U val) { 
    return T(); 
} 

int main() { 
    // error: no matching function for call to ‘fn(double)’ 
    // note: template argument deduction/substitution failed: 
    double d = fn(1.5); // fn<double>(1.5) will work 
} 

을 그리고 부분 특수화는 허용되지 않습니다 :

int fn(int) { return 0; } 
// error: new declaration ‘double fn(int)’ 
// error: ambiguates old declaration ‘int fn(int)’ 
double fn(int) { return 0; } 

는 U는하지 않을 것이다 기본 매개 변수로 T가있는 템플릿을 갖는 더 나은

template <typename T, typename U> 
T fn(U val) { 
    return T(); 
} 

// error: function template partial specialization ‘fn<T, T>’ is not allowed 
template <typename T> 
T fn<T, T>(T val) { 
    return T(); 
} 
+0

논리적으로 보입니다. 모든 정보가 함수에 주어 졌으므로 가능해야합니다. – Didii