2017-04-25 3 views
-1

비슷하지만 다른 템플릿 서명이있는 C++의 함수를 오버로드 할 수 있습니까?모호한 함수 오버로드 [예 : max()]

max() 함수를 고려하십시오. , *int 범위, int 반복자 범위의 한 쌍을 취할 수있는 max() 함수를 원하면 어떻게 될까요?

그래서 당신이 또는 C++에서 어떻게 그렇다면이 동작을 달성 할 수 있습니다 :

STL은 두 가지 기능으로이 기능 분할이있다?

편집 :이 경우 max(vec.begin(), vec.end());max(vec[0], vec[1]);이 성공적으로 컴파일되고 전달 된 두 객체의 최대 값과 최대 값을 찾습니다. 나는 개인적으로 STL에서 두 기능이 결합 될 수 없다고 생각하지만 그렇지 않다는 것을 확인했습니다.

+1

예, 가능합니다. 너 해봤 어? 어디서 곤경에 빠졌습니까? – aschepler

+0

함수 호출이 같은 이름의 함수 호출을 방해하지 않는 한 오버로드 문제가 있어서는 안됩니다 –

+0

'int max (const int * p);'와 같은 함수를 구현할 수 없습니다 얼마나 많은 int가'p '를 가리키는 지 알 수 없으므로,'int max (const int * begin, const int * end);와 같은 것을 원할 것이다. –

답변

1

지금 과부하는 제한하지 않았기 때문에 모호합니다. 첫 번째 컴파일러가 반복자에 사용되어서는 안된다는 것을 컴파일러가 어떻게 알았습니까?

대답은 간단합니다. 다행히 표준은 std::iterator_traits을 정의하며 전달 된 반복자 유형에 대한 모든 종류의 정보를 쿼리 할 수 ​​있습니다 (반복자 인 한).

여기서 마지막 점은 키입니다. std::iterator_tags<T>에 중첩 된 typedef iterator_category이없는 경우 T은 반복기가 아닙니다. 따라서 member detection using void_t을 사용하여 지정된 유형이 반복자인지 확인하는 사용자 정의 특성을 정의 할 수 있습니다. 코드에서

, 그것은 다음과 같습니다

여기
// C++17 void_t 
template <typename...> 
using void_t = void; 

template <typename T, typename = void> 
struct is_iterator : std::false_type { 
}; 

template <typename T> 
struct is_iterator<T, void_t<typename std::iterator_traits<T>::iterator_category>> : std::true_type { 
}; 

template <typename T> 
constexpr auto is_iterator_v = is_iterator<T>::value; 

가 나는 또한 편의를 위해 constexpr 변수 is_iterator_v을 정의했다.

std::enable_if과 함께이 특성을 사용하여 T이 반복자인지 여부에 따라 이전에 모호한 두 가지 오버로드 중 하나를 선택적으로 비활성화 할 수 있습니다. 그렇게하려면 템플릿 선언 template <typename T>을 각각 template <typename T, std::enable_if_t<is_iterator_v<T>, int> = 0>template <typename T, std::enable_if<!is_iterator_v<T>, int> = 0>으로 바꿉니다.

함께 최선을 다하는, 코드는 다음과 유사합니다 :

// C++17 void_t 
template <typename...> 
using void_t = void; 

template <typename T, typename = void> 
struct is_iterator : std::false_type { 
}; 

template <typename T> 
struct is_iterator<T, void_t<typename std::iterator_traits<T>::iterator_category>> : std::true_type { 
}; 

template <typename T> 
constexpr auto is_iterator_v = is_iterator<T>::value; 

template<typename T, std::enable_if_t<!is_iterator_v<T>, int> = 0> 
constexpr T maximum(T a, T b) 
{ 
    return (a > b) ? a : b; 
} 

template<typename Iter, std::enable_if_t<is_iterator_v<Iter>, int> = 0> 
constexpr Iter maximum(Iter begin, Iter end) 
{ 
    if(begin == end) { 
     return end; 
    } 
    auto max = begin; 
    for (; begin != end; ++begin) { 
     if(*begin > *max) { 
      max = begin; 
     } 
    } 
    return max; 
} 

당신은 또한 wandbox에 작업 예를 찾을 수 있습니다.

관련 문제