2016-10-21 4 views
1

나는 몇 시간 동안 내 머리를 아프게하고 있지만이 코드를 실행하려고 할 때 왜 오류가 발생하는지 이해할 수 없다. 내가 관리 시간은 표현 범위를 좁힐 수 있습니다 후 :하나의 템플릿 함수에 두 개의 다른 비교기를 전달할 수없는 이유는 무엇입니까?

문제가 발생
pastryPrice() 

- 당신이 볼 수 있듯이을, 내가

struct dialingAreaComp{ 
    inline bool operator()(const Deliver *d1, const Deliver *d2)const { 
     return d1->getDialingArea() < d2->getDialingArea(); 
    } 
}; 
struct pastryPrice { 
    inline bool operator()(const Pastry *p1, const Pastry *p2)const { 
     return p1->getPrice() < p2->getPrice(); 
    } 
}; 
template<class T> 
void sortCollection(T& collection) 
{ 
    if (typeid (collection) == typeid(vector <Deliver*>)) 
    { 
     sort(collection.begin(), collection.end(), dialingAreaComp()); 
     printCollection(collection); 
    } 
    else if (typeid (collection) == typeid(vector <Pastry*>)) 
    { 
     sort(collection.begin(), collection.end(), pastryPrice()); 
     printCollection(collection); 
    } 
    else { cout << "WRONG!"; } 
} 
분류의 하나 개의 템플릿 기능에 대한 다수의 비교기를 구축하기 위해 노력하고있어 내가 다섯 가지 오류를 받고 있어요

, 모두 같은 :

심각도 코드 설명 프로젝트 파일 라인 억제 상태 오류 C2664 '부울 베이커리 :: pastryPrice :: 연산자 (const pastry *, const pastry *) const ':'전달 * '에서'const Pastry * '로 인수 1을 변환 할 수 없음 bakery c : \ program files (x86) \ microsoft visual studio 14.0 \ vc \ include \ xutility 809

그리고 하나 더 :

심각도 코드 설명 프로젝트 파일 라인 억제 상태 오류 C2056 불법 식 베이커리 C : \ 프로그램 파일 (86) \ 마이크로 소프트 비주얼 스튜디오 14.0 \ VC의 \ 포함 \ xutility (809)

내가 위에서 쓴 표현을 벗을 때, 코드가 일뿐입니다. - 두 개의 다른 비교기를 하나의 템플릿 함수에 전달할 수없는 이유는 무엇입니까?

지금 :

C2264 한 함수를 호환 형의 파라미터를 전달해야 할 때 발생하는 컴파일러 에러이다.

하지만 배달 기능이 작동하고 배달 비교 기능을 사용하면 패스트리가 컴파일되므로 ... 호환되지 않는 유형은 무엇입니까?

+4

템플릿이 컴파일 타임에 평가되는 반면,'if' 문은 런타임에 평가되기 때문입니다. 그래서 항상 함수 호출 중 하나가 일치하지 않습니다. –

답변

4

템플릿 기능이 컴파일 타임에 평가되고 함수 호출 중 하나가 절대로 일치하지 않으므로 오류가 발생합니다. 대신 템플릿의 간단한 함수 오버로드를 사용

void sortCollection(vector <Deliver*>& collection) 
{ 
    sort(collection.begin(), collection.end(), dialingAreaComp()); 
    printCollection(collection); 
} 

void sortCollection(vector <Pastry*>& collection) 
{ 
    sort(collection.begin(), collection.end(), pastryPrice()); 
    printCollection(collection); 
} 
+0

굉장! 고마워요 - 내가 그 incom을 추측하지 않았을 것입니다 – prowler

+0

* 나는 그것이 호환되지 않는 부분이라고 생각하지 않았을 것입니다 ... 나는 creatin/여러 종류의 함수 호출을 피하려고했습니다. – prowler

+0

@prowler _ "나는 creatin/여러 정렬 함수 호출을 피하려고했습니다."_ 그로부터 많은 이득을 얻지는 못했을 것입니다. –

5

귀하의 문제는 두 가지에 관계없이 촬영하는 하나의 컴파일입니다.

나는 이것에 다르게 접근 할 것이다.

template<class A, class B> 
struct overload_t:A,B{ 
    using A::operator(); 
    using B::operator(); 
    overload_t(A a, B b):A(std::move(a)), B(std::move(b)){} 
}; 
template<class A, class B> 
overload_t<A,B> overload(A a, B b){ 
    return {std::move(a),std::move(b)}; 
} 

이렇게하면 두 개의 함수 개체 또는 람다를 오버로드 할 수 있습니다. (완벽한 전달은 varargs처럼 ... 추가 될 수 있었지만, 간단하게 유지했습니다).

이제 우리는 단순히 :

auto comp=overload(dialingAreaComp{}, pastryPrice{}); 
using std::begin; using std::end; 
std::sort(begin(collection), end(collection), comp); 

는 컴파일러는 우리를 위해 올바른 비교 기능을 선택합니다. 내가 거기에있는 동안 편평한 배열 지원.

using namespace std;을 사용하여 중지하십시오.


위 코드가 수행하는 작업은 두 개의 함수 객체를 하나의 코드로 통합하는 것입니다. using A::operator()using B::operator()은 모두 ()을 동일한 클래스로 이동시키고 일반적인 메서드 호출 오버로드 규칙을 사용하여 호출 할 때 C++에서 호출하도록 지시합니다. 코드의 나머지 부분은 과부하되는 유형을 추론하고이를 이동식으로 만드는 접착제입니다.

sort은 컨테이너 유형에 따라 컴파일 시간 결정 유형의 개체를 호출합니다. () 과부하 해결 (호출 시점에서 sort 이내)은 컴파일 타임에 비교할 오른쪽 본문을 선택합니다.

따라서 기술은 2 개 이상의 오버로드, 함수 포인터 및 전달 참조를 지원하도록 확장 될 수 있습니다. C++에서 오버로드 유형이 상위 유형을 추론하여 팩토리 기능의 필요성을 없애려면 일부 작업을 수행 할 수 있습니다.

+0

이것은 OP를위한 조금 과잉일지도 모른다. 하지만 너무 아름다워. 약간의 땜질과 함께 이것은 아마도 2 개의 과부하를 수용하는 것뿐만 아니라 만들 수 있습니다. – Hayt

+0

@hayt 예 쉽습니다. 나는 그것을 짧고 달콤하게 유지했다. – Yakk

+0

@Yakk 멋집니다! 왜 생성자'overload_t (A a, B b) : A (std :: move (a)), B (std :: move (b)) {}'가 필요한지 말할 수 있습니까? make-like 함수가 없으면 그냥'return {}; 할 수 있습니다. – vsoftco

관련 문제