2016-12-03 5 views
2

Koenig에 의해 Accelerated C++에서 가져온 컨테이너의 중앙값을 계산하는 다음 C++ 코드가 있습니다.C++ : 정렬 함수에 일관성있는 이름 사용 - 일관되지 않은 동작

median.h

#ifndef GUARD_median_h 
#define GUARD_median_h 

#include <stdexcept> 
#include <algorithm> 
#include <cstddef> 

template<class T, class Iterator> 
T median (Iterator begin, Iterator end) 
{ 
    size_t size = end - begin; 
    if (size == 0) 
     throw std::domain_error("median of an empty vector"); 

    sort(begin, end); 

    size_t mid = size/2; 

    return size%2 == 0 ? (begin[mid] + begin[mid-1])/2 : begin[mid]; 
} 
#endif 

median_test.cpp

#include <vector> 
#include <iostream> 
#include "median.h" 

using std::vector; using std::cin; 
using std::cout; using std::endl; 

int main() 
{ 
    vector<double> myVec; 

    cout << "Please enter integers: "; 

    double val; 
    while (cin >> val) { 
     myVec.push_back(val); 
    } 

    cout << "The median is: " << median<double>(myVec.begin(), myVec.end()) << endl; 

    return 0; 
} 

이 코드는 컴파일과 잘 실행됩니다. 하지만 약간의 수정이 배열보다는 그래서 같은 벡터 중간 기능 ...

median_test_array.cpp을 테스트 할 경우

#include <iostream> 
#include "median.h" 

using std::cin; 
using std::cout; using std::endl; 

int main() 
{ 
    double myVec[1000]; 

    cout << "Please enter integers: "; 

    double val; 
    size_t i = 0; 
    while (cin >> val) { 
     myVec[i++] = val; 
    } 

    cout << "The median is: " << median<double>(myVec, myVec+i) << endl; 

    return 0; 
} 

나는 다음과 같은 컴파일 오류 얻을 :

| => g++-6 -I. median_test_array.cpp 
In file included from median_test_array.cpp:2:0: 
median.h: In instantiation of 'T median(Iterator, Iterator) [with T = double; Iterator = double*]': 
median_test_array.cpp:19:60: required from here 
median.h:15:9: error: 'sort' was not declared in this scope 
    sort(begin, end); 
    ~~~~^~~~~~~~~~~~ 
median.h:15:9: note: suggested alternative: 
In file included from /usr/local/Cellar/gcc/6.2.0/include/c++/6.2.0/algorithm:62:0, 
       from median.h:5, 
       from median_test_array.cpp:2: 
/usr/local/Cellar/gcc/6.2.0/include/c++/6.2.0/bits/stl_algo.h:4727:5: note: 'std::sort' 
    sort(_RandomAccessIterator __first, _RandomAccessIterator __last, 
    ^~~~ 

정렬에 대한 정규화 된 이름 (std :: sort)을 지정하면이 오류가 사라지지만이 인스턴스에는 정규화 된 이름이 필요하지만 벡터 예제에는 필요하지 않은 이유가 무엇인지 알고 싶습니다.

+1

http://stackoverflow.com/questions/8111677/what-is-argument-dependent-lookup-aka-adl-or-koenig-lookup – Brian

답변

1

이것은 ADL입니다. 당신의 첫 번째 코드 샘플에 대한

, 그것은 구현이 네임 스페이스 std 내부 클래스로 std::vector::iterator를 선언 할 것으로 보인다 후 ADL이 적용됩니다, std::sort 유형 std::vector::iterator의 인수를 사용하여 호출에 대한 발견된다.

두 번째 코드 샘플의 경우 sort에 전달 된 인수는 double*이고 ADL은 더 이상 적용되지 않으며 sort이라는 이름을 찾을 수 없습니다.

이러한 동작은 보장되지 않습니다. 표준에서는 std::vector::iterator을 구현해야하는 위치를 지정하지 않으며 심지어 클래스 일 필요도 없으므로 한정자 std::을 지정하거나 using std::sort;과 함께 사용하는 것이 좋습니다.

2

첫 번째 코드는 이른바 Argument Dependent Lookup 때문에 컴파일되었습니다. std::vector<double>::iterator이 네임 스페이스 std에 속하므로 sort 함수도이 네임 스페이스에서 조회되었습니다.

포인터를 사용할 때 ADL이 없습니다. 따라서 컴파일러는 sort이라는 선언을 찾을 수 없습니다.

정규화 된 이름 std::sort을 사용하십시오.