2014-03-02 2 views
1

좋아요. 제목을 잘 설명했는지 모르겠으니 예제를 드리겠습니다. 나는 일련의 부동 소수점 수의 중간 값을 찾는 함수를 생각해 내고있다. C4172 경고"자동"반환 값 함수에 대해 값으로 반환하는 방법

: 반환 지역 변수의 주소 또는 일시적이

내가 decltype(*cbegin)를 교체 시도 내가 이것을 컴파일하려고하면 다음

//get the median of an unordered set of numbers of arbitrary type without modifying the 
    //underlying dataset 
    template <typename InputIterator> 
    auto Median(
     InputIterator const cbegin, 
     InputIterator const cend, 
     bool const abs = false // get the median of the absolute values rather than nominal values 
     ) -> decltype(*cbegin) 
    { 
     typedef std::iterator_traits<InputIterator>::value_type T; 

     std::vector<T> data; 
     data.reserve(std::distance(cbegin, cend)); 

     // get a copy of the values for sorting 
     for (InputIterator it = cbegin; it != cend; ++it) 
     { 
      if (abs) 
       data.push_back(std::abs(*it)); 
      else 
       data.push_back(*it); 
     } 

     // find the median 
     std::nth_element(data.begin(), data.begin() + data.size()/2, data.end()); 

     return data[data.size()/2]; 
    } 

는 출력 : 여기에 기능입니다 std::remove_reference<decltype(*cbegin)>::type 또는 std::iterator_traits<decltype(*cbegin)>::value_type으로 표시되지만 컴파일되지 않습니다.

간단한 해결책이 있습니까? InputIterator가 가리키는 유형을 반환하려면 어떻게해야합니까?

는 편집이 : 여기에 고정 된 버전의 피드백을 기반으로합니다

//get the median of an unordered set of numbers of arbitrary type without modifying the 
    //underlying dataset 
    template <typename RandomAccessIterator> 
    typename std::iterator_traits<RandomAccessIterator>::value_type Median(
     RandomAccessIterator const cbegin, 
     RandomAccessIterator const cend, 
     bool const abs = false // get the median of the absolute values rather than nominal values 
     ) 
    { 
     typedef std::iterator_traits<RandomAccessIterator>::value_type T; 

     std::vector<T> data(cbegin, cend); 

     // find the median 
     std::nth_element(data.begin(), data.begin() + data.size()/2, data.end(), 
      [abs](T const a, T const b) 
     { 
      return abs ? std::abs(b) > std::abs(a) : b > a; 
     }); 

     return data[data.size()/2]; 
    } 
+1

std::remove_reference<decltype(*cbegin)>::type를 사용하여 참조를 제거 할 수 있습니다 당신은'그것의 앞에'유형 이름 표준 : remove_reference을 typename' 스틱 경우 BTW'표준 : remove_reference : 유형'작동합니다 :: type'을 사용하지만, 아마도 'std :: iterator_traits'를 사용하는 것이 더 쉽습니다. –

+1

BTW 'abs'에 따라 적당한 술어로 ['std :: nth_element'] (http://en.cppreference.com/w/cpp/algorithm/nth_element)를 사용하여 복사를 단순화 할 수 있습니다. – juanchopanza

+1

템플리트 유형 매개 변수의 이름을 바꿔야합니다. 구현은 _InputIterators_와 함께 작동하지 않으며 _ForwardIterators_ 와도 작동하지 않습니다. – nosid

답변

3

당신은 템플릿 매개 변수로 iterator_traits를 사용할 수없는 decltype은 필요하지 :

template <typename InputIterator> 
typename std::iterator_traits<InputIterator>::value_type 
Median(
    InputIterator const cbegin, 
    InputIterator const cend, 
    bool const abs = false 
); 

참고 typename 키워드 - 그것의 무엇을 실종됐다 너의 시도에서.

2

컴파일러는 사용자에게 뭔가를 임시로 반환한다는 사실을 알려주고 있습니다.

decltype (* cbegin)은 참조이므로 (*it = 12과 같은 코드를 작성할 수 있습니다), data 안에있는 값을 임시로 반환합니다.

당신은

관련 문제