대신 잘못된 과부하를 선택 : 두 번째 search_with
호출, 컴파일러는 세 번째 오버로드를 선택하는 이유컴파일러는이 코드를 살펴 유효 과부하
#include <vector>
#include <functional>
template<typename RandIt, typename T, typename Pred>
auto search_with(RandIt begin, RandIt end, const T& value, Pred&& pred) noexcept {
//...
return begin;
}
template<typename RandIt, typename T>
auto search_with(RandIt begin, RandIt end, const T& value) noexcept {
return search_with(begin, end, value, std::less<T>{});
}
template<typename Array, typename T, typename Pred>
auto search_with(const Array& array, const T& value, Pred&& pred) noexcept {
return search_with(std::begin(array), std::end(array), value, std::forward<Pred>(pred));
}
int main() {
std::vector<int> v = { 1, 2, 3 };
search_with(v, 10, std::less<int>{}); // ok
search_with(v.begin(), v.end(), 10); // fail!
}
내가 이해가 안 돼요. 세 번째 오버로드를 주석 처리하면 코드가 잘 컴파일됩니다. 이는 두 번째 오버로드가 컴파일 될 때 무시되지 않고 유효한 오버로드 여야 함을 나타냅니다. 반복자 std::begin
(및 std::end
)의 더 전문화가 없으므로
그러나, 제 3 오버가 실패하는 선택된다 :
main.cpp: In instantiation of 'auto search_with(const Array&, const T&, Pred&&) [with Array = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; T = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; Pred = int]':
main.cpp:23:39: required from here
main.cpp:17:34: error: no matching function for call to 'begin(const __gnu_cxx::__normal_iterator<int*, std::vector<int> >&)'
return search_with(std::begin(array), std::end(array), value, std::forward<Pred>(pred));
~~~~~~~~~~^~~~~~~
I 반대 상황이 발생한다고 생각했을
: 제 과부하 폐기 컴파일에 실패하고 두 번째가 선택되기 때문에.
하지만 분명히 그렇지 않습니다. 그래서 여기서 무슨 일이 일어나고 있습니까? 잘못된 과부하가 선택된 이유는 무엇입니까? 두 번째 것보다 세 번째 오버로드가 더 좋은 이유는 무엇입니까?
SFINAE는 defintion이 아닌 함수 선언에 적용됩니다.이 때문에 enable_if가 템플릿 인수 또는 반환 값에 적용되는 이유는 이러한 코드를 본문에 부착하는 더 쉬운 옵션이 아니기 때문입니다. 선언 비트가 컴파일되지 않는 경우에만 함수가 무시됩니다. 제공된 인수는 세 번째 함수의 선언에서 올바르게 작동하므로 삭제되지 않습니다. – jaggedSpire
그러나 후행 반환 형식을 사용하면 작동하는 것으로 보입니다. http://coliru.stacked-crooked.com/a/5d3d34290d7beb1a – AndyG
@AndyG 아, 그건 SFINAE입니다. :) 감사합니다 – Rakete1111