2013-05-15 15 views
5

가속화 된 C++을 통해 작업하고 있습니다. & Ex에 문제가 발생했습니다. 10.2 질문에는 이전 챕터의 중간 값 함수를 다시 작성해야하므로 벡터 나 내장 배열을 사용하여 중간 값을 호출 할 수 있습니다. 중간 값 함수는 모든 산술 형 컨테이너를 허용해야합니다.템플릿 오류 : 일치하는 함수 호출이 없습니다.

나는 아래 중간 세부에 두 통화를 할 수 없습니다 - 나는

No matching function for call to 'median' 

내가 템플릿을 사용하는 경우 유형은 컴파일 타임에 알려진 것이 몇 가지 조사에서 수집 된 오류 메시지가 나타납니다. 이 문제가 근본적인 문제일까요? 어떻게 든 형식을 템플릿 인수로 전달할 수 있습니까?

여기에 지금까지 내 코드입니다 :

#include <iostream> 
#include <vector> 
#include <stdexcept> 
#include <algorithm> 
#include <cstddef> 

using namespace std; 

template <class Iterator, class Type> 
Type median(Iterator begin, Iterator end) 
{ 
    vector<Type> vec(begin,end); 
    typedef typename vector<Type>::size_type container_sz; 
    container_sz size = vec.size(); 

    if (size == 0) { 
     throw domain_error("median of an empty vector"); 
    } 

    sort(vec.begin(), vec.end()); 

    container_sz mid = size/2; 
    return size % 2 == 0 ? (vec[mid] + vec[mid - 1])/2 : vec[mid]; 
} 

int main() 
{ 
    vector<int> grades; 

    for (int i = 0; i != 10; ++i){ 
     grades.push_back(i); 
    } 

    const int int_array[] = {2, 9, 4, 6, 15}; 
    size_t array_size = sizeof(int_array)/sizeof(*int_array); 

    cout << median(int_array, int_array + array_size) << endl; //error here: Semantic Issue, No matching function for call to 'median' 
    cout << median(grades.begin(), grades.end()) << endl;  //error here: Semantic Issue, No matching function for call to 'median' " 

    return 0; 
} 
+1

반대 또한, 하나는 median<int>(grades.begin(), grades.end())를 호출해야합니다 등급 = {0, 1, 2, 3, 4 , 5, 6, 7, 8, 9}'및'auto size = vec.size();'(즉, typedef를 제거하는 것). 원한다면'endl'을''\ n "'로 대체 할 수도 있습니다. –

+0

첫 번째 패스 독자에게는 컴파일 타임 오류의 원인이되는 줄 (* 양쪽 모두 *를 포함하여)과 주석 (예 : // <== 여기 오류)을 표시하십시오. 즉,'Type' 템플릿 매개 변수는 작성중인 호출에서 추론 할 수 없으며 궁극적으로 핵심 문제입니다. 나는 표준 라이브러리가 제공하는 템플릿 ['iterator_traits'] (http://en.cppreference.com/w/cpp/iterator/iterator_traits)이 당신의 문제에 대한 깨끗한 해결책이라고 생각한다. – WhozCraig

+0

전체 오류 메시지를 포함하십시오. 일반적으로 함수 호출에서 어떤 유형이 추론되는지 알려주고 실제 예상되는 유형과 비교할 수 있습니다. –

답변

3

귀하의 오류가 제공되는 인수 할 수 없습니다 Type의 공제에 뿌리를두고있다. 당신은 다음과 같이 표준 라이브러리 클래스 iterator_traits를 사용하여이 작업을 수행 할 수 있습니다

template < 
    class Iterator, 
    class Type = typename std::iterator_traits<Iterator>::value_type> 
Type median(Iterator begin, Iterator end) 
{ 
    vector<Type> vec(begin,end); 

    typedef typename vector<Type>::size_type container_sz; 

    container_sz size = vec.size(); 

    if (size == 0) { 
     throw domain_error("median of an empty vector"); 
    } 

    sort(vec.begin(), vec.end()); 

    container_sz mid = size/2; 

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

클래스 iterator_traits은 실제로보다 반복하는 (좀 더 복잡 결정하기 위해 제공 반복자 유형을 해부한다,하지만 괜찮은입니다 개요). 작동 방식에 대한 자세한 내용은 class iterator_traits의 설명서를 참조하십시오. 반복자 값 유형을 결정하는 가장 편리한 메커니즘입니다.

참고 :이 작업을 수행 할 수있는 기본 템플릿 매개 변수 Type 선언의 의도하지 않은 바이 패스 없도록하기 :

template <class Iterator> 
typename std::iterator_traits<Iterator>::value_type median(Iterator begin, Iterator end) 
{ 
    if (begin == end) 
     throw domain_error("median of an empty vector"); 

    typedef typename std::iterator_traits<Iterator>::value_type Type; 
    std::vector<Type> vec(begin,end); 
    sort(vec.begin(), vec.end()); 

    typename std::vector<Type>::size_type mid = vec.size()/2; 
    return vec.size() % 2 == 0 ? (vec[mid] + vec[mid - 1])/2 : vec[mid]; 
} 

그것의 작은 밀도, 중간 물건의 대부분을 던졌습니다,하지만 당신은 응시하는 경우 얼마나 오래 작동하는지 이해할 수있을뿐만 아니라 템플릿 매개 변수 목록을 줄여서 정말로 신경 써야 할 한 가지만 사용할 수 있습니다. Iterator 유형은 사용자가 함수에 제공하는 매개 변수에 의해 쉽게 추론됩니다.

+0

필자는 문제에 대한 저자의 해결책에 대한 링크로 위의 내용을 게시했습니다 (https://github.com/bitsai/book-exercises/blob/master/Accelerated%20C%2B%2B/chapter10/10-2.hpp).) 제가 언급했듯이, 당신의 솔루션은 완벽 해 보입니다. 그러나 나는 그 책에서 우연히 만나지 않을 것입니다. – Octave1

+0

@ Octave1 마찬가지로. 그것이 의미가 있기를 바랍니다. – WhozCraig

+0

죄송합니다. 첫 번째 댓글이 게시되어 너무 빨리 게시되었습니다. 답변 해주셔서 감사합니다. 나는 iterator_traits가 유용 할 것이라고 생각한다. 필자가 이해할 수없는 것은 작성자의 해결책이 주어진 반복자 인수에서 유형을 추론하여 내 것과 같은 오류를 만드는 것으로 보인다는 것입니다. 어떤 아이디어? – Octave1

4

일반적으로이 문제를 해결하는 가장 좋은 방법은 위에서 설명한대로 iterator_traits을 사용하는 것입니다. 그러나 책에서 특정 질문 10.2에 대답하기 위해 (Iterator_trait 지식을 가정하지 않음) 다음과 같이 진행할 수 있습니다. - Iterator 클래스 대신 Note 클래스 유형이 먼저 나열되어야합니다. 당신이 C++ (11)를 사용하는 경우 벡터 '로 벡터를 초기화 할 수 있습니다 median(grades.begin(), grades.end())

#include <iostream> 
#include <vector> 
#include <stdexcept> 
#include <algorithm> 
#include <cstddef> 

using namespace std; 

template <class Type, class Iterator>  //the order allows the second template parameter type to be deduced (Iterator)           
Type median(Iterator begin, Iterator end) //while requiring you still provide the first type 
{ 

    vector<Type> vec(begin,end); 

    //typedef typename vector<Type>::size_type container_sz; 
    //container_sz size = vec.size() 
    auto size = vec.size(); 

    if (size == 0) { 
     throw domain_error("median of an empty vector"); 
    } 

    sort(vec.begin(), vec.end()); 

    //container_sz mid = size/2 
    auto mid = size/2; 

    Type ret = size % 2 == 0 ? (vec[mid] + vec[mid - 1])/2 : vec[mid]; 

    return ret; 
} 


int main() 
{ 

    vector<int> grades = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 

    const int int_array[] = {2, 9, 4, 6, 15}; 

    size_t array_size = sizeof(int_array)/sizeof(*int_array); 

    cout << median<int>(int_array, int_array + array_size) << endl; //must provide int here, in order to give the template the return type at compile time 
    cout << median<int>(grades.begin(), grades.end()) << endl; 


return 0; 

}

관련 문제