2013-04-02 5 views
4

push 함수는 main 함수에서 호출 될 때 사용됩니다. 그러나 주 함수의 인수가 포인터 인 경우에도 여전히 함수 void Push(const DATA_TYPE& newValue)이 사용됩니다.템플릿 포인터 변수를 허용하는 함수 오버로드

포인터를 허용하는 것이기 때문에 다른 것을 사용해서는 안됩니까? 포인터 변수가있는 경우 두 번째 함수의 인수를 재정의하려면 인수를 어떻게 변경합니까?

template<typename DATA_TYPE> 
void Push(const DATA_TYPE& newValue) 
{ 
    //do stuff 
} 

template<typename DATA_TYPE> 
void Push(const DATA_TYPE *newValue) 
{ 
    //do stuff 
} 
+0

http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/에서 살펴보십시오. Stephan-T-Lavavej-Core-Cpp-3-n은 모든 것이 잘 설명되어 있습니다. –

답변

4

문제는 const와 함께 출력합니다.

문제는 당신이 const가 아닌 개체 포인터로 Push(p)를 호출 할 때, DATA_TYPE = P* 설정 Push(const P* &)의 함수 서명을 제공 할 때, P * p 첫 번째 버전이 정확히 작동한다는 것입니다. 이에 비해 DATA_TYPE = P 인 두 번째 버전은 을 얻기 위해 유형 서명에 const을 추가해야합니다. 즉, 정확히 일치하므로 두 번째 버전 대신 첫 번째 버전이 선택됩니다.

여기에 무슨 일이 일어나고 있는지 명확하게 예입니다 :

다음은 예입니다 : const DATA_TYPE& newValue 그것이 const DATA_TYPE*& newValue을 포인터 참조로와 일치하는 경우는 거의 아무것도 일치하기 때문에

#include <iostream> 

class Foo 
{ 
    public: 
    template<typename DT> 
    void Push(const DT& newValue) 
    { 
     std::cout<<"In const DT& version"<<std::endl; 
    } 

    template<typename DT> 
    void Push(const DT *newValue) 
    { 
     std::cout<<"In const DT* version"<<std::endl; 
    } 
}; 

int main() 
{ 
    Foo f; 

    int i=7; 

    // Since i is not const we pickup the wrong version 
    f.Push(i); // const DT& (DT = int) 
    f.Push(&i); // const DT& (DT = int*) 

    // Here's using a const pointer to show it does the right things 
    const int * const_i_ptr = &i; 
    f.Push(const_i_ptr); // const DT* (DT = int); 

    // Now using a const object everything behaves as expected 
    const int i_const = 7; 
    f.Push(i_const); // const DT& (DT = int); 
    f.Push(&i_const); // const DT* (DT = int); 
} 
+0

이것은 참조 버전이 정확한 일치를 제공한다는 것을 의미 할 수도 있지만 포인터 버전은'non-const'에서'const' 포인터로 타입 변환을해야하기 때문에 참조 버전이 더 잘 맞습니다. – Keith

+0

@Keith 충분히 동의했으면 좋겠다. –

0

내가이 프로그램을 테스트 한

#include <iostream> 

template <typename T> 
void push(T&) 
{ 
    std::cout << "By ref" << std::endl; 
} 

template <typename T> 
void push(T*) 
{ 
    std::cout << "By ptr" << std::endl; 
} 

int main() 
{ 
    int x = 0; 
    push(x); 
    push(&x); 
    return 0; 
} 

By ref 
By ptr 
+1

차이점은 템플릿 ' void push (T *)'가 템플릿이며, 여기서'void Push (const DATA_TYPE * newValue)'는 템플릿이 아닙니다. 나는이 질문에 어떻게 관련이 있는지 보지 못한다. – Mankarse

+0

const로 시도 했습니까? –

+0

누락 된'const'. '& x'는 rvalue이며'non-const' ref에 바인딩 될 수 없습니다. –

0

그것은이다.

template<typename DATA_TYPE> 
void Push(const typename std::remove_pointer<DATA_TYPE>::type& newValue) 
{ 
    //do stuff 
} 

template<typename DATA_TYPE> 
void Push(const DATA_TYPE *newValue) 
{ 
    //do stuff 
} 

Nothe 그러나 그 서 템플릿은 일반적으로 const T& 잡아 모든 호출의 원인이됩니다 다른 템플릿 오버로드와 함께 const T& 일치하는, 그래서 당신은 일을 이런 식으로 일을 피해야한다 : 내가 쓰는 것이 내 머리의 상단에서 - std::remove_pointerdescribed here를 사용해보십시오 .

편집 : 그것은 조금 더 복잡합니다

내 앞의 코드가 정확하지 :

예상하고 적절한 CONST을 사용하도록 호출자를 강제하지 않는 한이 작동
#include <iostream> 
#include <type_traits> 

template<typename DATA_TYPE, bool is_pointer> 
struct helper; 

template<typename DATA_TYPE> 
struct helper<DATA_TYPE, true>{ 
    static void f(const typename std::remove_pointer<DATA_TYPE>::type*){ 
     std::cout << "Pointer" << std::endl; 
    } 
}; 

template<typename DATA_TYPE> 
struct helper<DATA_TYPE, false>{ 
    static void f(const DATA_TYPE&){ 
     std::cout << "Non-pointer" << std::endl; 
    } 
}; 

template<typename DATA_TYPE> 
void Push(const DATA_TYPE& newValue) 
{ 
    helper<DATA_TYPE, std::is_pointer<DATA_TYPE>::value >::f(newValue); 
} 

int main() 
{ 
    int i=0; 
    Push(i); 
    Push(&i); 
    return 0; 
} 

--ness, 나는 그것이 이전 솔루션만큼 매력적이지 않다는 것을 인정하지만)

+0

그런 식으로 인수 유형 공제를 할 수없는 것 같습니다 : http://ideone.com/Ift1s0 –

+0

@MichaelAnderson 제 편집을 봅니다 ... –

+0

시도하지 않았지만 훨씬 더 유망 해 보입니다. –

관련 문제